Why headers punch above their weight

Security headers are instructions your server sends with every response telling browsers to turn on protections that are off by default for backward compatibility. They cost nothing at runtime, deploy in one config change, and mitigate whole bug classes — clickjacking, protocol downgrade, MIME confusion, and much of the blast radius of script injection. They are also the first thing any external scanner (or attacker) reads about you.

The six that matter

1. Strict-Transport-Security (HSTS)

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

Tells browsers to refuse plain-HTTP connections to your domain for the next year, killing downgrade and cookie-stripping attacks after first contact. Serve it on every HTTPS response. Add preload only deliberately: the preload list bakes your domain into browsers, which is excellent and effectively irreversible — every subdomain must speak HTTPS forever.

2. Content-Security-Policy (CSP)

The heavyweight: a whitelist of what the page may load and execute, and the strongest mitigation for XSS actually shipping in browsers. It is also the only header here that can break your site, so stage it:

  1. Start with frame protection alone — it cannot break anything:
    Content-Security-Policy: frame-ancestors 'self'
    This replaces the legacy X-Frame-Options and stops clickjacking.
  2. Draft a real policy and ship it as Content-Security-Policy-Report-Only with a report-to endpoint; watch what would have been blocked.
  3. Tighten and promote to enforcing. Modern best practice favors nonce-based script-src with 'strict-dynamic' over ever-growing host whitelists.

3. X-Content-Type-Options

X-Content-Type-Options: nosniff

Stops browsers from second-guessing Content-Type and executing things that were never meant to be scripts. No legitimate reason to omit it; set it globally and move on.

4. Referrer-Policy

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

Controls how much of your URLs leak to other sites in the Referer header. The value above — full URL same-origin, origin only cross-origin, nothing on HTTPS→HTTP — is the modern default worth setting explicitly, and stops session tokens and private paths bleeding into third-party analytics.

5. Permissions-Policy

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

Declares which browser features your site (and embedded iframes) may use. Deny what you don't use; the win is that a compromised script or rogue embed cannot quietly request the camera.

6. Cookie flags (not a header, same audit)

Set-Cookie: session=…; Secure; HttpOnly; SameSite=Lax

Secure keeps cookies off plain HTTP, HttpOnly keeps them from JavaScript (limiting XSS fallout), SameSite is the structural CSRF defense. Any session cookie missing these is a finding on every scanner you'll meet.

What you can skip in 2026

  • X-XSS-Protection — the browser XSS auditor it controlled is gone from every modern engine; the header is a no-op (and was occasionally harmful). Its presence mostly signals an untouched config from 2018.
  • X-Frame-Options — superseded by frame-ancestors; keep it only for genuinely ancient browser support.
  • Expect-CT, Public-Key-Pins — both deprecated; certificate transparency is now enforced by CAs and browsers without your participation.

Deploy once, then watch for drift

Set these at the outermost layer that sees every response — CDN, load balancer or reverse proxy — rather than per-application, so new services inherit them. Then verify from outside: securityheaders.com or Mozilla Observatory for a snapshot. The failure mode that remains is drift: a CDN migration or a new subdomain that ships without the config. Headers are part of what continuous external monitors (Bastion among them) re-check on every scan, precisely because a header that silently vanished looks identical to one that was never set.

Frequently asked questions

What are the most important HTTP security headers?

In rough priority order: Strict-Transport-Security (forces HTTPS), Content-Security-Policy — at minimum its frame-ancestors directive against clickjacking — X-Content-Type-Options: nosniff, Referrer-Policy, and Permissions-Policy, plus Secure/HttpOnly/SameSite flags on cookies. All except a full CSP can be deployed safely in an afternoon.

Is X-XSS-Protection still needed in 2026?

No. Chrome, Edge and Firefox all removed or never shipped the XSS auditor the header controlled, so modern browsers ignore it entirely. The real XSS mitigation is a Content-Security-Policy with nonce-based script-src.

Will adding security headers break my website?

Four of them — X-Content-Type-Options, Referrer-Policy, Permissions-Policy and frame-ancestors 'self' — are near-zero-risk for typical sites. HSTS is safe if all your subdomains already serve HTTPS (be cautious with includeSubDomains and preload if not). A full Content-Security-Policy is the one that can break things, which is why it ships in report-only mode first.