Security-Headers Plugin

The Security-Headers plugin adds essential HTTP security headers to responses, protecting against common web vulnerabilities like XSS, clickjacking, and content type sniffing. It implements security best practices through headers like CSP, HSTS, and X-Frame-Options.

Overview

Modern web applications face numerous security threats that can be mitigated through proper HTTP security headers. This plugin automatically adds these headers to all responses, implementing defense-in-depth security. It provides sensible defaults while allowing customization for specific application needs. The plugin is HTTPS-aware and only adds HSTS headers over secure connections.

Key Features

Configuration

The security-headers plugin is configured as part of the plugin pipeline in your host configuration:

<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/security-headers.so</span>
    <meta itemprop="csp_policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'">
    <meta itemprop="hsts_max_age" content="31536000">
    <meta itemprop="frame_options" content="DENY">
</li>

Configuration Parameters

Parameter Type Required Default Description
csp_policy String No See below Content Security Policy directives
hsts_max_age Integer No 31536000 HSTS max-age in seconds (default: 1 year)
hsts_include_subdomains Boolean No true Apply HSTS to all subdomains
hsts_preload Boolean No false Enable HSTS preload list submission
frame_options String No "SAMEORIGIN" X-Frame-Options value: DENY, SAMEORIGIN
content_type_options Boolean No true Add X-Content-Type-Options: nosniff
referrer_policy String No "strict-origin-when-cross-origin" Referrer-Policy value
permissions_policy String No None Permissions-Policy directives
xss_protection String No "1; mode=block" X-XSS-Protection value

Security Headers Explained

Content Security Policy (CSP)

CSP helps prevent XSS attacks by controlling which resources can be loaded:

Default CSP:

default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'

Common CSP Directives:

HTTP Strict Transport Security (HSTS)

HSTS forces browsers to use HTTPS connections:

Warning: HSTS headers are only added over HTTPS connections. Ensure your server is properly configured for HTTPS before enabling HSTS with long max-age values.

HSTS Directives:

X-Frame-Options

Prevents clickjacking by controlling framing:

Referrer-Policy

Controls how much referrer information is sent:

Plugin Pipeline Placement

Note: The security-headers plugin should be placed near the end of the pipeline to ensure headers are added to all responses, including error pages.

Typical pipeline order:

1. basic-auth.so      → Authentication
2. file-handler.so    → Content serving
3. error-handler.so   → Error pages
4. security-headers.so → Add security headers ✓
5. access-log.so      → Logging

Examples

Basic Security Headers

<!-- Use all defaults -->
<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/security-headers.so</span>
</li>

Strict CSP for Modern Apps

<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/security-headers.so</span>
    <meta itemprop="csp_policy" content="default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'">
    <meta itemprop="frame_options" content="DENY">
</li>

CSP with External Resources

<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/security-headers.so</span>
    <meta itemprop="csp_policy" content="default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:">
</li>

HSTS with Preload

<!-- Only enable preload after testing! -->
<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/security-headers.so</span>
    <meta itemprop="hsts_max_age" content="63072000"> <!-- 2 years -->
    <meta itemprop="hsts_include_subdomains" content="true">
    <meta itemprop="hsts_preload" content="true">
</li>

Permissions Policy

<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
    <span itemprop="library">file://./plugins/security-headers.so</span>
    <meta itemprop="permissions_policy" content="accelerometer=(), camera=(), geolocation=(self), microphone=()">
</li>

Testing Security Headers

Using curl

# Check all response headers
curl -I https://example.com

# Check specific header
curl -I https://example.com | grep -i "content-security-policy"

# Verbose output
curl -v https://example.com 2>&1 | grep -E "^< " | grep -i security

Online Testing Tools

Browser Developer Tools

  1. Open Developer Tools (F12)
  2. Go to Network tab
  3. Reload the page
  4. Click on the main document request
  5. Check Response Headers section

Common CSP Configurations

Static Site (No JavaScript)

default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'

Single Page Application

default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com; font-src 'self'

With Google Analytics

default-src 'self'; script-src 'self' https://www.google-analytics.com; img-src 'self' https://www.google-analytics.com; connect-src 'self' https://www.google-analytics.com

Development Mode

default-src * 'unsafe-inline' 'unsafe-eval' data: blob:; frame-ancestors *
Warning: Never use development mode CSP in production!

Security Best Practices

Troubleshooting

Common Issues

Issue Cause Solution
Scripts not loading CSP blocking inline or external scripts Add script sources to script-src or use nonces
Styles broken CSP blocking inline styles Add 'unsafe-inline' to style-src or refactor to external CSS
HSTS not working Not using HTTPS HSTS only works over HTTPS connections
Iframe not displaying X-Frame-Options DENY Change to SAMEORIGIN or adjust frame-ancestors
Fonts not loading Missing font-src directive Add font sources to font-src in CSP

CSP Debugging

Check browser console for CSP violations:

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'"

Debug Logging

Run the server with -v flag to see header additions:

./rusty-beam -v config.html

Browser Compatibility

Header Chrome Firefox Safari Edge IE11
CSP Partial
HSTS
X-Frame-Options
Permissions-Policy Partial

Performance Impact

Integration with Other Plugins

CORS Plugin

The CORS plugin handles cross-origin headers separately. Both plugins can work together.

Compression Plugin

Security headers are added after content compression, so they're not affected by the compression plugin.

WebSocket Plugin

CSP's connect-src directive affects WebSocket connections. Configure appropriately for WebSocket usage.

See Also