I scanned the homepages of a bunch of companies I respect last week, and the results surprised me. Not the small startups. The big, security-literate ones. Netlify's homepage is missing four of the six security response headers that browsers act on. Stripe, Vercel, and OpenAI all land in the A range, but plenty of sites you'd assume are buttoned-up are sitting at a C.
This isn't a "gotcha" post. Missing headers is the single most common thing I find, and it's usually nobody's fault. The framework ships without them, the CDN doesn't add them by default, and there's no error in the console telling you they're gone. The site works. It quietly trusts the browser to do the safe thing when you could have told the browser exactly what to do.
So here's the short version of which headers matter, what each one buys you, and a free way to check your own site in about ten seconds.
The six that move the needle
There are a lot of HTTP headers. Only a handful change your real exposure. These are the ones I grade on.
1. Strict-Transport-Security (HSTS). Tells the browser "only ever talk to me over HTTPS, don't even try plain HTTP." Without it, the first request a returning visitor makes can go out over http:// before the redirect kicks in, and that first hop is where a network attacker lives. One line:
Strict-Transport-Security: max-age=31536000; includeSubDomains
2. Content-Security-Policy (CSP). The big one, and the one most sites skip because it's the most work. CSP is your defense against cross-site scripting: it tells the browser which sources of script, style, and content are allowed to run. If someone manages to inject a <script> into your page, a good CSP is what stops it from executing. Start in report-only mode so you don't break your own site:
Content-Security-Policy-Report-Only: default-src 'self'
Watch the violation reports for a week, tighten, then switch to enforcing. It's the header with the best payoff and the steepest setup, which is exactly why so many A-looking sites don't have it.
3. X-Content-Type-Options. One value, no debate:
X-Content-Type-Options: nosniff
This stops the browser from guessing that your .txt upload is "probably JavaScript" and running it. MIME sniffing is an old foot-gun and this header turns it off.
4. Clickjacking protection (X-Frame-Options or CSP frame-ancestors). Stops other sites from loading yours inside a hidden iframe and tricking users into clicking things they can't see. If you don't need to be embedded anywhere:
X-Frame-Options: DENY
Or the modern equivalent inside your CSP: frame-ancestors 'none'.
5. Referrer-Policy. Controls how much of your URL gets leaked to other sites when a user clicks an outbound link. If your URLs carry tokens or IDs in the path or query string, the default behavior can hand those to whatever you linked to. A sane default:
Referrer-Policy: strict-origin-when-cross-origin
6. Permissions-Policy. Lets you switch off browser features you don't use, like camera, microphone, and geolocation, so a compromised script can't quietly ask for them.
Permissions-Policy: camera=(), microphone=(), geolocation=()
That's the whole list. Six headers. Most of them are one line, and four of the six are copy-paste with no tuning. CSP is the only one that takes real thought.
Why "the site works" hides the problem
The reason this stuff drifts is that nothing breaks when a header is missing. There's no red text, no failing test, no Lighthouse score tanking. A page missing every security header renders identically to one that's locked down tight. You only find out the gap exists when someone goes looking, and by then it's usually a pentest invoice or an incident.
The other trap is the forced-HTTPS redirect. People assume that because they "have HTTPS," they're covered. But if http://yoursite/ quietly serves your content instead of returning a 308 to the HTTPS version, then every link anyone ever shares as http:// lands a real visitor on the insecure path. Netlify, to their credit, gets this one right. A surprising number of sites that look modern don't.
Checking yours without installing anything
You can read all of this off the raw response yourself:
curl -sI https://yoursite.com | grep -iE 'strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy'
Anything that doesn't print is a header you're missing. That's the honest, no-tools way, and if you only have one site to check it's genuinely the fastest.
If you want it graded and want the one-line fix for each gap spelled out, I built a small thing for that. It's called SiteGuard: paste a URL, get an A to F grade in a few seconds, with the specific fix for everything it flags. No account, no email wall, nothing stored against you unless you explicitly save a shareable report.
It only reports what it observes on your live response, so every "fail" is a real header that wasn't there, not a generic checklist item. I built it because I wanted exactly this check for my own projects without handing some SaaS my domain and getting dripped at forever.
Run it on your own site before you read further into your day. If you come back with an A, you were already in good shape. If you come back with a C, you're in extremely normal company, and now you've got the six-line fix.
What's the most-missed header you run into in code review? I'll bet it's CSP, but I've been wrong about this before.
Top comments (0)