Guide

What Do Security Headers Like CSP and HSTS Actually Do

· 7 min read

Security headers such as HSTS, CSP, and X-Frame-Options block real browser attacks, but the wrong value can break your own checkout or embeds.

In short

Security headers are instructions your server sends to every visitor's browser, telling it to refuse things a normal page would otherwise allow, like loading a script from a random domain or being embedded inside someone else's frame. HSTS forces encrypted connections, CSP restricts where content can load from, X-Frame-Options and Referrer-Policy limit framing and address leakage. SiteHealth checks whether your site sends these headers at all, because most sites that lack them show no error, no warning, and no reason to suspect anything is wrong.

What are website security headers, and why do they matter?

A security header is a line in your server's HTTP response, invisible on the page itself, that tells the visitor's browser to enforce a rule. The browser already has these protections built in; the header just switches them on for your domain. Without the header, the browser falls back to its permissive default, which is the setting attackers count on.

This matters because the failures these headers prevent do not look like failures. A page missing Content-Security-Policy still loads fine. A page missing X-Frame-Options still looks normal in a browser tab. The problem only shows up when someone embeds your login page in an invisible frame over their own malicious page, or injects a script through a comment field that a CSP would have blocked outright. Nothing on your side ever throws an error, because the attack succeeds silently, which is exactly why most owners never think to check.

How does HSTS actually protect a visitor?

HTTP Strict Transport Security, or HSTS, tells the browser to never load your site over plain HTTP again, not even for the first request. Without HSTS, a visitor typing your domain without "https://" gets sent to the encrypted version by a redirect, and that one plain-HTTP request before the redirect is a window an attacker on the same network, such as public wifi, can intercept and rewrite.

With HSTS set and cached by the browser, that window closes. The browser refuses to even attempt the plain connection and goes straight to HTTPS. The header includes a max-age in seconds (a common starting value is one year, 31536000) and an optional includeSubDomains flag that extends the rule to every subdomain. The Mozilla HSTS reference covers the exact syntax. Once a browser has cached a long max-age, removing HSTS later does not help visitors who already saw it, so raise the value gradually rather than starting at the maximum. A missing certificate causes the same kind of silent risk from a different angle — see why an SSL certificate can expire without warning.

What does a Content-Security-Policy header block?

Content-Security-Policy, or CSP, is an allow-list for where your page is permitted to load scripts, styles, images, and fonts from. Anything not on the list is blocked by the browser itself, before it ever runs. This is the header that stops a large share of cross-site scripting attacks, where an attacker gets malicious JavaScript to run on your page through a comment box, a search field, or a compromised third-party script.

A minimal starting policy looks like this:

  • default-src 'self' — only load resources from your own domain unless another directive says otherwise
  • script-src 'self' https://js.stripe.com — scripts only from your domain and any payment processor you use
  • form-action 'self' https://checkout.stripe.com — forms can only submit to your domain or your checkout provider
  • frame-ancestors 'self' — nobody else can embed your pages in a frame
  • object-src 'none' — block Flash and other plugin content outright, almost nobody needs this anymore

The most common CSP mistake is writing it once, deploying it, and then finding out in production that a chat widget, an analytics tag, or a font service silently stopped working, because it was never on the allow-list. Most browsers support a report-only mode (Content-Security-Policy-Report-Only) that logs violations without blocking anything, which is the right way to find every third-party script you actually depend on before you enforce the policy for real. The OWASP CSP cheat sheet is a good primary reference for writing your first policy.

X-Frame-Options and Referrer-Policy: what do they stop?

X-Frame-Options tells the browser whether your page is allowed to be loaded inside a frame on another site. Set to DENY or SAMEORIGIN, it stops a specific attack called clickjacking, where an attacker overlays your real page (invisibly) on top of a fake button, so a visitor thinks they are clicking a harmless link but is actually clicking your "delete account" or "confirm payment" button underneath. The newer frame-ancestors directive inside CSP does the same job and is the current standard, but keeping X-Frame-Options alongside it costs nothing and covers older browsers that only read the legacy header.

Referrer-Policy controls what address information the browser hands to the next site when a visitor clicks a link away from your page. Left at the browser default, the full URL of the page they were on, including anything in the query string, gets sent along. A value of strict-origin-when-cross-origin sends only your bare domain to outside sites, and the full path only when the link stays on your own domain, which is the setting the W3C Referrer Policy specification lists as a reasonable modern default.

Which headers should you add first, and in what order?

Adding all of these at once, on a site that has never had any of them, is how a Friday deployment turns into a Saturday spent guessing what broke. A safer order:

  1. Add X-Content-Type-Options: nosniff and Referrer-Policy: strict-origin-when-cross-origin first. Both are close to zero risk and rarely break anything on a normal site.
  2. Add X-Frame-Options: SAMEORIGIN (or DENY if nothing of yours is ever meant to be embedded elsewhere).
  3. Turn on HSTS with a short max-age, such as a few hours, confirm nothing broke, then raise it toward a year over the following days.
  4. Deploy Content-Security-Policy in report-only mode and read the violation reports for at least a few days of real traffic, including your busiest page and your checkout flow.
  5. Convert the CSP to full enforcement once the report-only period shows no unexpected blocks, and recheck it after any change to third-party scripts, embeds, or payment providers.

Checking these by hand once catches today's setup. It does not catch the header that a CDN change, a hosting migration, or a rewritten server config quietly drops three weeks from now, which is the actual failure mode worth planning for.

What breaks when you turn these headers on, and how do you catch it early?

The honest risk with security headers is not that they are hard to write, it is that a wrong or missing entry blocks something real without printing an error anywhere a human would see it. A CSP missing your payment processor's domain does not show a warning banner, it just makes the "Pay now" button silently do nothing. A CSP missing your form action target does the same to a contact form, which is the same silent-failure pattern as a contact form that says thank you but sends nothing. This is exactly why SiteHealth checks for missing or misconfigured browser protections as part of the same hourly scan that watches your certificate, your email records, and your forms — see the full list of checks on the features page. It is a plain-English addition to a routine you should already have, not a separate task.

"My developer already handled security, why check headers separately?"

Most sites had headers set correctly once, at launch, by whoever built them. Headers live in server config, a CDN rule, or a proxy layer, not usually in application code, so they are easy to lose during a migration, a platform switch, or a "quick fix" to an unrelated routing rule, and nothing about that change looks dangerous at the time. A header disappearing causes no downtime and no visible error, so the gap can sit open for months before anyone notices, usually only after something goes wrong.

Check your headers today

Run the free check against your own domain. It reads the response headers your server is actually sending right now, tells you in plain English which of HSTS, CSP, X-Frame-Options, and Referrer-Policy are missing or weak, and what each one is protecting against. No account is required and it takes about twenty seconds.

FAQ

Questions people ask about this

What is the difference between HSTS and SSL?

SSL, or more accurately TLS, is the encryption that protects a connection once it is set up. HSTS is a header that tells the browser to always use that encrypted connection for your domain, so it never tries plain HTTP first. A site can have valid TLS and still skip HSTS, leaving the first request on any visit exposed.

Will adding a Content-Security-Policy header break my site?

It can, if you write it wrong. A CSP header lists exactly which sources are allowed to load scripts, styles, and images, and anything not on that list is silently blocked, including scripts you forgot about like a chat widget or an analytics tag. Test in report-only mode first so you see what would break before anything actually does.

Do I need X-Frame-Options if I already have a CSP?

The frame-ancestors directive inside CSP does the same job and is the newer standard, but a small number of older browsers only honor X-Frame-Options. Setting both costs nothing and covers the gap, so most current guidance is to keep X-Frame-Options as a fallback alongside frame-ancestors.

What does Referrer-Policy actually stop?

By default, when a visitor clicks a link on your site, their browser can send the full URL they came from, including anything in the query string, to the next site. Referrer-Policy controls how much of that address gets shared. A setting like strict-origin-when-cross-origin sends just your domain name to other sites and the full address only to your own pages.

Can I test my security headers without paying for anything?

Yes. Several free header-checking tools exist, and you can also open your browser's network tab, reload your homepage, and read the response headers on the first request by hand. What is harder to do for free is catch the day a header silently disappears after a hosting change, which is what ongoing monitoring is for.

Why did my security headers disappear after a server change?

Most security headers on a shared or managed host are not set by your application code at all, they are set in a server config block, a CDN rule, or a reverse proxy. A hosting migration, a CDN change, or a config rewrite commonly drops them without any error, because a missing header causes no crash, only a quieter, less protected page.