HeaderAudit

The security header checklist, in the order worth doing them

Security header guides tend to list a dozen headers as equally important. They are not. This is the order that buys the most protection per unit of work, based on what each one actually prevents.

1. Strict-Transport-Security

Strict-Transport-Security: max-age=31536000; includeSubDomains

Do this first because it is one line, breaks nothing once you are https-only, and closes an attack that requires no bug on your part. Redirecting http to https is not sufficient — the first plaintext request is interceptable before your redirect arrives.

Add includeSubDomains once every subdomain serves https. Cookies are shared up the domain tree, so a single plaintext subdomain undermines the parent.

2. X-Content-Type-Options

X-Content-Type-Options: nosniff

One value, no configuration, prevents the browser second-guessing your Content-Type and executing an uploaded file as script. It occasionally surfaces an existing bug where you serve JavaScript or CSS with the wrong type — that is worth knowing about anyway.

3. Frame protection

Content-Security-Policy: frame-ancestors 'none'

Prevents clickjacking. Use CSP frame-ancestors rather than X-Frame-Options: it supports a list of origins, and browsers that support it ignore X-Frame-Options anyway. If you need to support genuinely ancient browsers, set both — it is harmless, and the CSP value wins where both are understood.

Never rely on X-Frame-Options: ALLOW-FROM. No current browser implements it, so a policy depending on it provides no protection at all.

4. Content-Security-Policy

The highest-value header and by far the most work, which is why it is fourth rather than first — the three above are quick wins you should not delay behind it.

Start report-only. See the CSP guide.

5. Referrer-Policy

Referrer-Policy: strict-origin-when-cross-origin

This is the modern browser default, so setting it explicitly changes little — but it removes the dependency on that default and protects against URLs containing tokens or identifiers leaking to third parties. Watch for unsafe-url, which sends full URLs everywhere.

6. Permissions-Policy

Permissions-Policy: camera=(), microphone=(), geolocation=()

Deny what you do not use. The reason this matters is embedded frames: a third party in your page can prompt for camera access, and the prompt looks like it came from you.

Advice that is now wrong

  • X-XSS-Protection: 1; mode=block — the auditor this controlled was removed from every browser because it was bypassable and introduced its own vulnerabilities. Set 0 or remove the header.
  • Public-Key-Pins (HPKP) — removed from browsers. It made permanent, unrecoverable site outages easy to cause.
  • X-Frame-Options: ALLOW-FROM — never widely implemented.
  • Expect-CT — obsolete. Certificate Transparency is now enforced by default.

Where to set them

At the edge, not in application code — a CDN or reverse proxy rule covers every response including static files and error pages, which is exactly where application-level middleware tends to miss. The one exception is CSP with a nonce, which must be generated per response and so has to come from the application.

Check a site