secure-os.org
All guidesQubes OSTailsWhonixHardened LinuxDisk encryptionThreat model
headers

Security Headers Checklist: Six Lines, and What 301 Public Bodies Actually Send

secure-os· Updated September 6, 2026· 4 min read #headers#web security#csp#measurement
Two people looking at a printed home inspection checklist on a wooden clipboard, its coloured sections ticked with a pen, hands and torsos visible but faces out of frame

Six response headers are the ones every hardening guide lists. Each costs a line or two of server configuration, and our own measurement below shows how unevenly they are actually sent.

We measured it rather than assumed it. On 6 September 2026 we requested the homepage of 336 public organisations, one request each, and read the response headers. 301 answered usably.

Strict-Transport-Security 171 / 301 56.8 % X-Content-Type-Options 180 / 301 59.8 % X-Frame-Options 175 / 301 58.1 % Referrer-Policy 145 / 301 48.2 % Content-Security-Policy 128 / 301 42.5 % Permissions-Policy 55 / 301 18.3 %

none of the six : 78 sites all six : 32 sites

One organisation in four sends not a single one of them. That is the finding, and it is worth more than another list of recommended values.

The six, in the order worth deploying them

Strict-Transport-Security tells the browser to use HTTPS for this host from now on, so a later request typed as http:// never leaves the machine in the clear. Start with a short max-age while you confirm nothing breaks, then raise it.

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

â›” includeSubDomains applies to every subdomain, including any internal one still on plain HTTP. Check before adding it, because the browser will remember.

X-Content-Type-Options: nosniff stops the browser guessing a content type when yours looks wrong. One line, no configuration, no way for it to break a normal site. This is the cheapest of the six and 121 of the 301 sites still do not send it.

X-Frame-Options: DENY prevents your pages being embedded in a frame elsewhere, which is what clickjacking needs. Its modern replacement is frame-ancestors in a Content Security Policy; sending both is normal while older browsers remain in use.

Referrer-Policy limits what the destination learns about where a visitor came from. strict-origin-when-cross-origin sends the full path within your own site and only the origin to third parties, which is the usual balance.

Content-Security-Policy is the powerful one and the only one that takes real work, because a policy that is too tight breaks your own pages. Deploy it in report mode first:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

Read the reports for a week, then switch to the enforcing header. A policy written blind and enforced immediately is how sites break their own analytics and fonts on a Friday evening.

Permissions-Policy disables browser features you never use, camera and microphone and geolocation among them. It is the least deployed of the six by a wide margin, and the least risky to add for a site that uses none of those features:

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

Low angle view of a neoclassical government building facade, a long curved colonnade of stone columns above a rusticated base, in black and white

Checking your own site takes one command

curl -sI https://example.com | grep -iE "strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy"

Nothing printed means none of the six are set. That is the same command we ran 336 times, and it is the only measurement that matters for your own domain.

Three honest caveats about this list

Headers are not a security posture. They constrain what a browser does with a page you already serve correctly. They do nothing about an authentication flaw, an exposed admin panel, or an unpatched dependency, and a perfect header score on a vulnerable application is a decoration.

Our figures are a snapshot. They describe 301 sites on one day. A site measured then may have changed since, and the date is part of the data rather than a footnote to it.

Permissions-Policy being rare is not automatically a failing. It is a newer header, it is optional, and a site that uses no camera or microphone loses nothing measurable by omitting it. We report the number because it is the clearest gap in the set, not because 18.3 % is a scandal.

Where the numbers come from

The relevé was produced with an open source collector, poids-compression-sites-publics and its companion header script, both MIT licensed, one request per domain and no API key. The raw CSV is kept alongside the tooling so the figures above can be recounted rather than trusted.

Related reading on this site: Linux hardening for the server side, and what is a threat model for deciding which of these six actually matter to you.