Security headers are the lowest-effort, highest-impact security improvement you can make to a web application. They're response headers that instruct the browser to enable built-in security features — and they take minutes to implement.
Yet in our audits, over 70% of applications are missing at least three critical security headers.
The Essential Headers
73%
Missing CSP
61%
Missing HSTS
44%
Missing X-Frame-Options
38%
Missing Permissions-Policy
Content-Security-Policy (CSP)
criticalThe most powerful security header. CSP tells the browser which sources of content are trusted, effectively neutralizing most XSS attacks.
Without CSP
- •Injected script tags execute immediately
- •Inline event handlers (onclick, onerror) run attacker code
- •Data exfiltration via img src to attacker server
- •Malicious iframes load phishing pages
With CSP
- •Only scripts from whitelisted domains execute
- •Inline scripts blocked unless nonce-based
- •Connections restricted to known origins
- •Frame sources explicitly controlled
💡Start with Report-Only
Deploy CSP in report-only mode first (Content-Security-Policy-Report-Only) to identify violations without breaking your application. Fix violations, then switch to enforcement.
Strict-Transport-Security (HSTS)
highForces browsers to only connect via HTTPS, preventing SSL stripping attacks.
Recommended value: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age=31536000— Remember for 1 yearincludeSubDomains— Apply to all subdomainspreload— Submit to browser preload lists so even the first visit is HTTPS
⚠️HSTS Preload Is Permanent
Once you submit to the HSTS preload list and browsers ship the update, there is no quick way to undo it. Make sure all your subdomains support HTTPS before adding includeSubDomains and preload.
X-Frame-Options / frame-ancestors
mediumPrevents your site from being embedded in iframes on other domains — the primary defense against clickjacking.
X-Frame-Options: DENY— Never allow framingX-Frame-Options: SAMEORIGIN— Only allow framing by your own domain- Modern alternative:
Content-Security-Policy: frame-ancestors 'self'
Permissions-Policy
Controls which browser features your site can use — camera, microphone, geolocation, payment API, etc.
Recommended: Disable everything you don't need:
Permissions-Policy Strategy
Deny by default
Start with a restrictive policy that disables all features: camera=(), microphone=(), geolocation=(), payment=()
Enable only what you use
If your app needs geolocation: geolocation=(self). If you embed a payment iframe: payment=(self "https://payments.example.com")
Prevent feature abuse
Even if an attacker achieves XSS, they can't access the camera, microphone, or other sensitive APIs if the permissions policy blocks them.
Other Important Headers
Additional Security Headers
X-Content-Type-Options: nosniff
Prevents browsers from MIME-sniffing a response away from the declared Content-Type. Stops attacks where an attacker uploads a .jpg that's actually JavaScript.
Referrer-Policy: strict-origin-when-cross-origin
Controls how much referrer information is sent with requests. Prevents leaking sensitive URL parameters to third parties.
Cross-Origin-Opener-Policy: same-origin
Isolates your browsing context from cross-origin windows. Prevents Spectre-style side-channel attacks and cross-window manipulation.
Cross-Origin-Resource-Policy: same-origin
Prevents other origins from reading your resources. Blocks unauthorized cross-origin data access.
Implementation by Platform
Nginx
ℹ️Nginx Configuration
Add headers in your server block: add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always;
Next.js
Use the headers() function in next.config.js to set headers on all routes. For CSP with nonces, use middleware to generate a per-request nonce.
Express.js
Use the helmet middleware — it sets sensible security headers with one line: app.use(helmet()). Customize individual headers as needed.
Cloudflare / CDN
Most CDNs support adding response headers at the edge. This is often the easiest approach for static sites and ensures headers are set even if your application server misconfigures them.
Testing Your Headers
Scan
Use securityheaders.com or our AI scanner to check your current headers
Implement
Add missing headers in report-only mode first
Test
Verify your application still works — CSP is the most likely to break things
Enforce
Switch from report-only to enforcement after fixing violations
The Quick Win
Security headers are one of the few areas where you can significantly improve your security posture in under an hour. Start with these five, in order of impact:
- Content-Security-Policy — Neutralizes most XSS
- Strict-Transport-Security — Forces HTTPS everywhere
- X-Content-Type-Options — Prevents MIME confusion
- X-Frame-Options — Blocks clickjacking
- Permissions-Policy — Restricts browser feature access
Our AI scanner checks all security headers automatically as part of every audit. Run a scan to see exactly which headers your application is missing — and get implementation guidance for each one.