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.
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.
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>
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 |
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:
default-src
: Fallback for other directivesscript-src
: Controls JavaScript sourcesstyle-src
: Controls CSS sourcesimg-src
: Controls image sourcesconnect-src
: Controls AJAX/WebSocket connectionsfont-src
: Controls font sourcesframe-ancestors
: Controls framing (like X-Frame-Options)HSTS forces browsers to use HTTPS connections:
HSTS Directives:
max-age
: How long to remember HTTPS requirementincludeSubDomains
: Apply to all subdomainspreload
: Allow inclusion in browser preload listsPrevents clickjacking by controlling framing:
DENY
: No framing allowedSAMEORIGIN
: Only same-origin framingControls how much referrer information is sent:
no-referrer
: Never send referrersame-origin
: Only for same-origin requestsstrict-origin-when-cross-origin
: Full URL for same-origin, origin only for cross-originTypical 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
<!-- Use all defaults -->
<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
<span itemprop="library">file://./plugins/security-headers.so</span>
</li>
<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>
<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>
<!-- 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>
<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>
# 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
default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'
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'
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
default-src * 'unsafe-inline' 'unsafe-eval' data: blob:; frame-ancestors *
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 |
Check browser console for CSP violations:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'"
Run the server with -v
flag to see header additions:
./rusty-beam -v config.html
Header | Chrome | Firefox | Safari | Edge | IE11 |
---|---|---|---|---|---|
CSP | ✓ | ✓ | ✓ | ✓ | Partial |
HSTS | ✓ | ✓ | ✓ | ✓ | ✓ |
X-Frame-Options | ✓ | ✓ | ✓ | ✓ | ✓ |
Permissions-Policy | ✓ | ✓ | Partial | ✓ | ✗ |
The CORS plugin handles cross-origin headers separately. Both plugins can work together.
Security headers are added after content compression, so they're not affected by the compression plugin.
CSP's connect-src directive affects WebSocket connections. Configure appropriately for WebSocket usage.