Skip to content
Security Medium severity By Lewis Jones

Missing Security Headers: HSTS & CSP

What HSTS, CSP, X-Frame-Options and X-Content-Type-Options do, an example finding, how to add each one, and when the check stays quiet.

Four response headers control whether a browser trusts your site's connection, whether it can be embedded in someone else's page, and whether it renders a file exactly as declared. None of them show up to a visitor when they are missing. They show up the day something goes wrong.

What this finding means

Crawl Cove's security-headers check reads the response headers on every indexable HTML page and flags whichever of these are absent:

  • Strict-Transport-Security (HSTS), only checked on pages already served over HTTPS.
  • Content-Security-Policy (CSP), checked on every page.
  • X-Frame-Options, checked on every page, unless the CSP already declares a frame-ancestors directive (modern browsers use that instead and ignore X-Frame-Options when both are present).
  • X-Content-Type-Options, which must equal exactly nosniff; any other value counts as missing, because that is the only value the spec defines.

A page served over plain http:// is flagged directly for that instead of "missing HSTS": there is nothing for HSTS to upgrade if the page was never secure to begin with.

A real finding looks like this:

Missing security headers: Content-Security-Policy, X-Frame-Options, X-Content-Type-Options

One finding per page listing everything that is absent, not one finding per missing header.

Why it matters

These headers are what stops a browser from downgrading the connection, framing your pages inside someone else's site for clickjacking, or executing a script the server never intended to serve. Their absence is invisible to a visitor until the day it is exploited.

How to fix it

Each header is added the same way regardless of CMS: as a response header from your web server or CDN.

Apache (.htaccess):

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy "default-src 'self'"

Nginx (server block):

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "default-src 'self'" always;

Heads up

Add Content-Security-Policy last, and expect to tune it. A policy of default-src 'self' blocks any script, style or embed loaded from a third-party domain, which breaks analytics tags, fonts and embedded widgets that legitimately need to load from elsewhere. Add each third-party domain your page genuinely uses to the policy, checking your browser's console for blocked-resource warnings as you go, rather than shipping a policy nobody tested.

If you are on shared or managed hosting with no access to server config, check whether your host or CDN (such as Cloudflare) offers these headers as a dashboard toggle instead.

False positives and edge cases

  • X-Frame-Options is correctly skipped when your CSP already declares frame-ancestors. Modern browsers use that CSP directive and ignore X-Frame-Options when both are present, so the check does not ask you to add a header that would do nothing.
  • HSTS is only scored on HTTPS pages. A plain http:// page is flagged for that directly, not for "missing HSTS", since there is nothing to upgrade yet.
  • X-Content-Type-Options must be exactly nosniff. Any other value, including a near-miss typo, counts as absent, because the spec defines no other valid value.

Related reading

For the check that covers an HTTPS page loading an insecure http:// resource, see Mixed Content.

Google documentation: Security headers quick reference

Frequently asked questions

Do these headers go in my CMS admin?
Usually not. They are HTTP response headers, so they are typically set in server config (.htaccess on Apache, a server block on Nginx) or at your CDN, not in a WordPress or Shopify settings screen.
Which header should I add first?
Content-Security-Policy and X-Content-Type-Options are the two flagged regardless of scheme, so they apply to every site. HSTS only applies once you are already on HTTPS.
Will a strict Content-Security-Policy break my site?
It can, if the policy is stricter than the scripts and styles your page actually loads. Start with a policy that allow-lists your own domain plus anything you know you embed, and check the browser console for blocked-resource warnings after you add it.
Does adding these headers help SEO directly?
Not as a scored ranking factor, but they are the baseline a security-conscious buyer or auditor checks for, and Google has said page experience and trustworthiness matter for how a site is perceived.

Audit your site the easy way

Crawl Cove finds this on your machine, on every paid plan. Try the SEO Audit or see every feature.

Download Crawl Cove