HTTP security headers explained: HSTS, CSP and more
Updated 2026-10-26 ยท Draft, not yet reviewed
Response headers tell the browser how to treat a site: whether to insist on HTTPS, where scripts may come from, who may show the page in a frame and how much of the address to pass on to other sites. They do not change the page, but they limit what an attacker can do with it. The security headers check follows a site's redirects and reads these headers from the final HTTPS response.
HTTP to HTTPS
Visitors who type a bare name, or follow an old link, start on http://. The server should answer with a permanent redirect (301 or 308) to the same path on https://. Without it they stay on a connection that anyone on the path can read and change: HTTP_NO_HTTPS_REDIRECT. The check reports this whenever the HTTP chain does not end on HTTPS, whatever the redirect status.
A redirect alone still leaves the first request unencrypted, and an attacker can intercept it. That is what HSTS closes.
Strict-Transport-Security (HSTS)
RFC 6797 defines a header that tells the browser to use only HTTPS for the host for max-age seconds:
Strict-Transport-Security: max-age=31536000; includeSubDomains
max-ageis required. A header without a valid max-age, or with a directive repeated, is ignored by the browser, and the check counts it as missing (HSTS_MISSING).includeSubDomainsextends the rule to every subdomain.- The browser processes only the first
Strict-Transport-Securityheader of a response, and only over HTTPS.
Roll it out in steps: start with a few minutes or a day, check that nothing breaks, and then raise the value. One year (31 536 000 seconds) is the usual end state; below that the check gives HSTS_SHORT_MAX_AGE as information.
Preloading
HSTS works from the second visit. To cover the first one too, browsers ship a list of preloaded domains, managed through hstspreload.org. Its requirements are a valid certificate, a redirect from HTTP to HTTPS on the same host if port 80 answers, HTTPS on all subdomains, and an HSTS header on the base domain with max-age of at least 31 536 000, includeSubDomains and preload. HSTS_NOT_PRELOAD_READY lists what is missing. Removal from the list takes months to reach users, so preload only domains that will stay HTTPS-only everywhere.
Content Security Policy
A Content Security Policy (W3C CSP Level 3) lists where a page may load scripts, styles, images and frames from. Its main use is to make cross-site scripting much harder: an injected script that does not come from an allowed source does not run.
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0m'; frame-ancestors 'self'
script-srccontrols scripts; without it,default-srcapplies.'unsafe-inline'allows any inline script and removes most of the protection. With a nonce or hash in the same directive, browsers that support CSP Level 2 or later ignore it.'unsafe-eval'allowseval()and is not made safe by a nonce. Both cases giveCSP_UNSAFE_INLINE.Content-Security-Policy-Report-Onlysends reports but blocks nothing. It is the safe way to try a policy first, but it does not count as protection (CSP_MISSING).
Whether a site needs a strict policy depends on what it does, which is why the check reports CSP findings as information.
Frame protection
A page shown inside another site's frame can be overlaid with misleading buttons, so that a visitor clicks something they did not mean to (clickjacking). frame-ancestors in a Content Security Policy, or the older X-Frame-Options: DENY or SAMEORIGIN, prevents that. With neither, the check reports FRAME_PROTECTION_MISSING.
Other headers
X-Content-Type-Options: nosniffstops browsers from guessing a response's type from its content (XCTO_MISSING).Referrer-Policydecides how much of the page address is sent to other sites. Current browsers default tostrict-origin-when-cross-origin; setting it makes the behaviour the same everywhere (REFERRER_POLICY_MISSING).Permissions-Policyturns off browser features the site does not use, such as the camera or geolocation.Cross-Origin-Opener-Policy: same-originseparates the page from windows opened by or opening other sites.
Cookies
A cookie without the Secure attribute is also sent over plain HTTP, where it can be read (COOKIE_NOT_SECURE). HttpOnly keeps a cookie away from JavaScript, and SameSite=Lax or Strict keeps it off most cross-site requests. Session cookies should have all three.
A safe order
- Serve every page over HTTPS with a valid certificate (see the TLS certificates guide).
- Redirect HTTP to HTTPS permanently.
- Add
X-Content-Type-Options, frame protection and aReferrer-Policy. - Add HSTS with a short max-age, then raise it to a year.
- Write a Content Security Policy, run it as Report-Only, fix what it reports and then enforce it.
- Consider preloading only when every subdomain is HTTPS-only.
HTTP findings
- Warning
HTTP_NO_HTTPS_REDIRECTPlain HTTP is not redirected to HTTPS. - Info
HTTP_UNAVAILABLEThe site does not answer over plain HTTP.
HTTPS findings
- Error
HTTPS_UNAVAILABLEThe site could not be loaded over HTTPS.
Redirects findings
- Warning
REDIRECT_LIMITThe site redirects more than five times in a row. - Info
REDIRECT_OFFSITEThe site redirects to another domain.
HSTS findings
- Warning
HSTS_MISSINGThe HTTPS site sends no valid Strict-Transport-Security header. - Info
HSTS_NOT_PRELOAD_READYThe domain does not meet the HSTS preload requirements. - Info
HSTS_SHORT_MAX_AGEThe HSTS max-age is shorter than one year.
Content Security Policy findings
- Info
CSP_MISSINGThe HTTPS site sends no Content-Security-Policy header. - Info
CSP_UNSAFE_INLINEThe Content Security Policy allows inline or eval'd scripts.
X-Content-Type-Options findings
- Info
XCTO_MISSINGThe HTTPS site sends no X-Content-Type-Options: nosniff header.
Frame protection findings
- Info
FRAME_PROTECTION_MISSINGThe HTTPS site does not restrict who may frame it.
Referrer-Policy findings
- Info
REFERRER_POLICY_MISSINGThe HTTPS site sends no Referrer-Policy header.
Cookies findings
- Warning
COOKIE_NOT_SECUREThe HTTPS site sets a cookie without the Secure attribute.
Frequently asked questions
Which security headers matter most?
A redirect from HTTP to HTTPS and a Strict-Transport-Security header matter for nearly every site, because they keep visitors on encrypted connections. X-Content-Type-Options: nosniff and frame protection are cheap and rarely cause problems. A Content Security Policy gives the most protection against cross-site scripting, but it needs the most work to get right.
Is HSTS preloading a good idea?
Only when every subdomain works over HTTPS and will keep doing so. Preloaded domains are built into browsers, so a mistake cannot be undone quickly: removal takes months to reach users. Check every subdomain first, then send includeSubDomains with a short max-age, raise the max-age in steps, and add preload last.
Why is 'unsafe-inline' in a CSP a problem?
Most cross-site scripting injects inline script. A policy that allows 'unsafe-inline' for scripts lets that script run, so it gives little protection. With nonces or hashes, browsers that support CSP Level 2 or later ignore 'unsafe-inline' and run only the scripts you marked. The security headers check reports the unsafe case as CSP_UNSAFE_INLINE.
Do I still need X-Frame-Options?
The frame-ancestors directive of Content Security Policy replaces it, and browsers that support both follow frame-ancestors. X-Frame-Options is still useful as a fallback for old browsers, and it is easier to add when there is no CSP yet.