HTTP Security Headers Checklist
debt(d5/e3/b3/t5)
Closest to 'specialist tool catches it' (d5). The detection_hints list securityheaders.com, owasp-zap, ssllabs, and lighthouse — all specialist/external scanning tools. Missing headers are not caught by a compiler or default linter; you need to actively run one of these scanners against a deployed site. They won't surface during local development unless deliberately invoked.
Closest to 'simple parameterised fix' (e3). The quick_fix is essentially 'run securityheaders.com and add the six standard headers to your server config.' Adding/correcting headers is a small, well-scoped change — typically a few lines in nginx/Apache config or a middleware file. However, CSP in particular may require iterative tuning (removing unsafe-inline, adding nonces), pushing it slightly above e1 to e3.
Closest to 'localised tax' (b3). The applies_to scope is 'web' contexts only. Once headers are set correctly at the server/middleware level, ongoing maintenance is modest — primarily CSP requires periodic review as third-party scripts change. The rest of the codebase is largely unaffected, so the structural burden is limited to the web-serving layer.
Closest to 'notable trap' (t5). The misconception field explicitly states that security headers are treated as set-and-forget, when CSP in particular requires ongoing maintenance. Common mistakes reinforce this: CSP with 'unsafe-inline' (negates XSS protection), HSTS missing includeSubDomains, and setting headers in PHP rather than the web server. These are documented gotchas that most developers learn only after a problem surfaces.
Also Known As
TL;DR
Explanation
Key security headers: Content-Security-Policy (controls which resources can load — mitigates XSS), Strict-Transport-Security (forces HTTPS for a duration), X-Frame-Options / frame-ancestors (prevents clickjacking), X-Content-Type-Options: nosniff (prevents MIME sniffing), Referrer-Policy (controls what referrer is sent), Permissions-Policy (disables browser features like camera/microphone). Tools: securityheaders.com grades your headers. Add headers in nginx config, not PHP, for performance.
Common Misconception
Why It Matters
Common Mistakes
- CSP with 'unsafe-inline' — negates most of the XSS protection; use nonces or hashes instead.
- HSTS without includeSubDomains — subdomains can still be attacked over HTTP.
- Setting security headers in PHP instead of nginx/Apache — adds overhead on every request; set at the server level.
- Not testing headers with securityheaders.com or Mozilla Observatory after deployment.
Code Examples
# nginx — no security headers:
server {
listen 443 ssl;
location / {
proxy_pass http://app:9000;
# No security headers — fails any security audit
}
}
# nginx — full security header set:
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload' always;
add_header X-Frame-Options 'DENY' always;
add_header X-Content-Type-Options 'nosniff' always;
add_header Referrer-Policy 'strict-origin-when-cross-origin' always;
add_header Permissions-Policy 'geolocation=(), microphone=(), camera=()' always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-$csp_nonce'; style-src 'self' 'unsafe-inline'" always;
# Test at: https://securityheaders.com