Which security headers do you need and what do they do?
An ordinary site needs six: HSTS, Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, X-Frame-Options and Permissions-Policy. Five of them are a single line in the server config, while CSP needs tuning — which is exactly why it gives the most.
Security headers are instructions telling the browser what it may do with your page. Without them a browser behaves in the most permissive way available — not because that is safe, but because old sites would otherwise break.
Six of them close most of the gap. Five are one line each.
Five you can add right now
Strict-Transport-Security — for a year the browser will not even try HTTP.
Closes the first-visit window where someone types the address without https://.
X-Content-Type-Options: nosniff — forbids the browser from guessing a
file's type. Without it an uploaded "image" can be executed as a script.
Referrer-Policy — how much of the address goes to another site. Without it
the full URL, parameters included, travels to every link target.
X-Frame-Options: SAMEORIGIN — stops your page being placed in someone
else's frame. Protects against a click that looks like one thing and is another.
Permissions-Policy — switches off what the page does not need: camera,
microphone, geolocation, payments.
The sixth: Content-Security-Policy
CSP declares where the browser may load scripts, styles and images from. It is the only header that genuinely stops injected code — and the only one that, added carelessly, stops the page working.
So it gets tuned in steps:
Content-Security-Policy-Report-Only— the policy applies but blocks nothing, it only reports;- collect the reports, add the sources that are genuinely needed;
- only then switch to enforcing mode.
The first version is almost always too strict. That is normal — it is what
Report-Only exists for.
What an ordinary site does NOT need
Two things scanners ask for, and both cost an ordinary site more than they give:
Cross-Origin-Embedder-Policy applies to embedded frames too: every
iframe must declare the same policy. Add it and payment windows, maps and bot
protection typically stop working.
require-trusted-types-for demands that every write into the DOM goes
through an approved policy. Most libraries do not create one, so the result is a
broken page.
Both are needed when a site requires cross-origin isolation. Demanding them from an ordinary site is inventing a problem.
Related articles
The same subject from another angle — each answers its own question:
- Website security check: what to look at
- Technical SEO audit: what to check and when
- Free SEO scan: what it actually shows you
How this feeds into the score is described under what we check.
Sources
What this text rests on — primary sources, not retellings:
Frequently asked
Is the HSTS preload list worth joining?
Only when you are certain. Joining means browsers will never try HTTP for your domain **and all its subdomains**, and removal takes months. One forgotten internal subdomain without a certificate becomes unreachable.
Where should these headers go?
In the server or CDN configuration, not in application code. That way they also apply to static files and error pages — which is exactly where they usually go missing.
Does CSP protect against everything?
No. It protects against injected script execution. It does nothing about a stolen password or a hole in the server.
How do I check they are working?
In browser developer tools, under "Network", select the first request and read the response headers. That shows exactly what the server sends.
Check yours
A free scan shows which of the things described here your site already does, and which it does not.