What security headers actually do (and which ones you don’t need)

Response headers aren’t a security score, and a missing one isn’t automatically a vulnerability. Each does one specific, narrow job — worth understanding before treating a scanner’s checklist as gospel.

Strict-Transport-Security (HSTS)

Tells the browser to only ever connect to this domain over HTTPS, for a set period of time, without needing an initial redirect. Without it, a user typing a bare domain (no https://) makes one plain-HTTP request before any redirect happens — a small window where that first request could be intercepted. HSTS closes that window, but only after the browser has seen the header at least once, and only for the duration of max-age. It mitigates a specific downgrade scenario; it doesn’t make a site secure on its own.

Content-Security-Policy (CSP)

Restricts which sources a page is allowed to load scripts, styles, and other resources from. Its main practical benefit is reducing the blast radius of a cross-site-scripting bug: even if an attacker manages to inject a script tag, a well-configured CSP can stop the browser from executing it. A CSP that allows unsafe-inlinefor scripts gives up most of that protection — the header being present doesn’t mean it’s doing anything meaningful, which is why a checker should flag what the policy allows, not just whether the header exists.

Clickjacking protection (X-Frame-Options / frame-ancestors)

Controls whether the page can be embedded in an <iframe>on another site — the defense against clickjacking, where a page is invisibly framed to trick a user into clicking something they didn’t mean to. CSP’s frame-ancestors directive is the modern replacement for the older X-Frame-Options header and supports more granular allow-lists; either is fine, having neither is the actual gap.

X-Content-Type-Options

A single value, nosniff, that stops the browser from trying to guess a response’s content type instead of trusting the declared Content-Type header. MIME-sniffing is what could otherwise let a file uploaded as, say, an image get interpreted and executed as something else. Cheap to set, narrow in scope — a real but small mitigation, not a headline security control.

The ones that are genuinely optional

Cross-Origin-Resource-Policy and Cross-Origin-Embedder-Policy exist to support cross-origin isolation — mainly relevant if a site uses features like SharedArrayBufferor wants to guarantee other sites can’t load its resources. Most sites need neither. A checker that flags their absence as a generic “missing header” problem, with no context, is producing noise rather than signal — this is exactly why the HTTP Security Headers Checker marks these “not applicable” rather than “missing” when absent.