The 10 Most Common Security Header Mistakes (and How to Fix Them)
Security headers are the cheapest hardening you can ship — and the easiest to get subtly wrong. Here are the ten mistakes scanners flag most, with the exact fix for each.
HTTP response headers are the rare security control that costs a few lines of config and protects every visitor immediately. That is also why getting them wrong is so common: they are easy to copy-paste and hard to test. These are the ten issues that show up over and over in scan results.
1. No HSTS (or HSTS without the preload path)
Without Strict-Transport-Security, a single plaintext request can be intercepted before the HTTPS redirect. Set a long max-age and include subdomains:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadOnly add preload once every subdomain is HTTPS-only — it is hard to undo quickly.
2. A Content-Security-Policy that allows unsafe-inline
script-src 'unsafe-inline' re-opens the exact XSS hole CSP exists to close. Move to nonces or hashes:
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}'; object-src 'none'; base-uri 'self'3. Shipping CSP in report-only mode forever
Content-Security-Policy-Report-Only is for the rollout phase. Plenty of sites leave it there for months, collecting reports while enforcing nothing. Use report-only to find violations, then switch to the enforcing header once it is quiet.
4. X-Frame-Options instead of frame-ancestors
X-Frame-Options is legacy and cannot express an allow-list. Prefer the CSP directive, which modern browsers honor:
Content-Security-Policy: frame-ancestors 'self'5. Missing X-Content-Type-Options
Without X-Content-Type-Options: nosniff, a browser may MIME-sniff a response and execute something you served as text. It is a single header with no downside — always set it.
6. A dangerous or absent Referrer-Policy
The default leaks full URLs (including tokens in query strings) to third parties. A safe, broadly compatible choice:
Referrer-Policy: strict-origin-when-cross-origin7. Permissions-Policy left at the browser default
If your app does not use the camera, microphone or geolocation, say so explicitly so a compromised script cannot either:
Permissions-Policy: camera=(), microphone=(), geolocation=()8. Setting headers on HTML but not on the API
Headers applied by a frontend framework often miss API routes, redirects and error pages. Scanners test those paths directly. Set security headers at the edge — a reverse proxy, CDN or platform middleware — so coverage is uniform.
9. Conflicting headers from multiple layers
When both your app and your CDN set Content-Security-Policy, the browser may see two headers and apply the *intersection*, silently breaking features. Decide on one authoritative layer and remove the duplicates.
10. Caching sensitive responses
Authenticated pages and API responses with personal data should not be cacheable by shared proxies:
Cache-Control: no-storeConfirm with a re-scan
Headers interact, so change them in small batches and re-scan after each. If you are new to reading the results, start with How to Read a Website Security Scan Report; for the transport layer underneath these headers, see SSL/TLS Misconfigurations That Put Your Site at Risk. The full header check runs on every scan — see all checks on the features page.
Turn these checks into a scan report for your own site.
Run a free scan and get prioritized, actionable findings in about 30 seconds.
Scan my siteKeep reading
How to Read a Website Security Scan Report
A scan returns dozens of findings and a score. Here is how to turn that output into a short, prioritized fix list without drowning in noise.
SSL/TLS Misconfigurations That Put Your Site at Risk
A valid padlock does not mean your TLS is healthy. These are the certificate and protocol misconfigurations that quietly weaken HTTPS, and how to catch them.