12 Security Headers You Must Set Before Going to Production
CSP, HSTS, X-Frame-Options and the rest. A plain-English reference for every HTTP security header your web app should set before launch.
HTTP security headers are the cheapest, highest-leverage security improvement you can make to a web app. They're a few lines of config, they're free, and they shut down entire classes of attacks.
Here's every header you should set, what it does, and the gotchas.
1. Content-Security-Policy (CSP)
The big one. CSP tells the browser which sources of content are allowed. Done right, it makes XSS dramatically harder to exploit.
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';
Gotcha: 'unsafe-inline' for scripts defeats most of CSP's purpose. The goal is to remove it. Use nonces or hashes for inline scripts. Start permissive, tighten with Content-Security-Policy-Report-Only first, then enforce.
2. Strict-Transport-Security (HSTS)
Forces HTTPS. Once a browser sees this header, it refuses to talk to your site over plain HTTP for the duration specified.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Gotcha: Don't enable preload casually — it's a one-way door. Once you're on the HSTS preload list, removing your site takes months. Make sure you're ready for HTTPS-only, forever, on all subdomains.
3. X-Frame-Options
Prevents clickjacking by controlling who can embed your site in an iframe. Largely superseded by CSP's frame-ancestors, but still worth setting for older browsers.
X-Frame-Options: DENY
4. X-Content-Type-Options
Stops browsers from MIME-sniffing — guessing a file's type from its content rather than trusting the declared type. Prevents a class of XSS where an uploaded "image" is actually HTML.
X-Content-Type-Options: nosniff
5. Referrer-Policy
Controls how much referrer information the browser sends when navigating away from your site.
Referrer-Policy: strict-origin-when-cross-origin
This sends the full origin for same-origin requests, but only the origin (not path/query) for cross-origin HTTPS requests, and nothing for HTTPS to HTTP.
6. Permissions-Policy
Formerly Feature-Policy. Lets you disable browser features you don't use — camera, microphone, geolocation, payment — so a compromised script can't access them.
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
7. Cross-Origin-Opener-Policy (COOP)
Isolates your browsing context group, defending against Spectre-class attacks that leak data across origins.
Cross-Origin-Opener-Policy: same-origin
8. Cross-Origin-Embedder-Policy (COEP)
Required for cross-origin isolation. Blocks no-cors cross-origin loads unless they opt in via CORP or CORS.
Cross-Origin-Embedder-Policy: require-corp
Gotcha: COEP can break third-party embeds (images, scripts, iframes) that don't send CORP headers. Test carefully.
9. Cross-Origin-Resource-Policy (CORP)
Declares who is allowed to load this resource. Default for your own assets should be same-origin.
Cross-Origin-Resource-Policy: same-origin
10. X-DNS-Prefetch-Control
Controls browser DNS prefetching. Minor, but useful to set explicitly.
X-DNS-Prefetch-Control: on
11. X-Permitted-Cross-Domain-Policies
Restricts Adobe Flash/PDF cross-domain loading. Mostly historical, but harmless and expected by scanners.
X-Permitted-Cross-Domain-Policies: none
12. Cache-Control for sensitive responses
Not strictly a security header, but critical: pages with user-specific or sensitive data should never be cached by shared proxies.
Cache-Control: no-store
How to verify
Once you've set them, verify with:
- securityheaders.com — free, grades your headers A+ to F
- Mozilla Observatory — broader security posture check
- Your browser's DevTools → Network → click the document → Headers
The minimum viable set
If you do nothing else, set these four: CSP, HSTS, X-Frame-Options, X-Content-Type-Options. That alone shuts down the majority of automated attack traffic looking for easy targets.
Then run the ShipReady Security section to catch the rest.
Run the full checklist
Put this into practice — generate a stack-specific production readiness checklist and track your progress, free.
Open the checklistGet new articles in your inbox
Practical production readiness guides. No spam, unsubscribe anytime.
Join developers shipping safer. We email ~2× per month.
Keep reading
What Is a Zip Bomb? The 42KB File That Crashes Servers (DoS Explained)
A 42 KB file that expands to 4.5 petabytes. Here's how zip-bomb denial-of-service attacks work, the real numbers behind the famous 42.zip, and how to defend against them.
DoS vs DDoS vs Decompression Bomb: A Developer's Field Guide
They're not the same attack, and they don't have the same defense. Here's the difference — and the interview-ready way to explain it.
Rate Limiting in Production: The Most Underrated Security Control
Ten lines of code that stop 90% of automated abuse — credential stuffing, brute force, scraping, API abuse. Here's how to actually do it.