Skip to content
Security

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.

January 22, 2025 8 min readBy ShipReady

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 checklist

Get new articles in your inbox

Practical production readiness guides. No spam, unsubscribe anytime.

Join developers shipping safer. We email ~2× per month.

Keep reading