SiteScan.top

HTTP security headers: the minimum worth setting today

CSP, HSTS, X-Content-Type-Options and the rest: what actually protects you, what is obsolete, and in which order to roll them out without an outage.

Security · Published: 10 June 2026 · 3 min read · Марк Лебедев

Security headers are one of the rare cases where a few lines of configuration close whole classes of attack. And one of the rare cases where a careless rollout breaks the site in seconds. So the order matters as much as the content.

Start with the safe ones

These three can be enabled with almost no risk:

X-Content-Type-Options: nosniff — stops the browser guessing content types. It closes the scenario where a user-uploaded "text" file is executed as a script.

Referrer-Policy: strict-origin-when-cross-origin — stops leaking the full page path into somebody else's analytics. It is the browser default today, but stating it explicitly is more reliable.

Strict-Transport-Security: max-age=31536000; includeSubDomains — HSTS forces HTTPS. Careful: enable it only once the whole site and every subdomain already run on HTTPS. There is no fast rollback — browsers remember the header for the entire max-age. Start at max-age=300, confirm nothing broke, then raise it.

CSP — the most useful and the most dangerous

Content-Security-Policy declares where scripts, styles and images may be loaded from. It blocks most XSS, and it takes the site down if the policy was written on a hunch.

The right path has three steps:

  1. Turn on observation mode: Content-Security-Policy-Report-Only with a reporting endpoint. Nothing is blocked, but you see what would be.
  2. Collect reports for a couple of weeks and add everything legitimate to the policy — widgets, fonts, analytics.
  3. Switch to the enforcing header.

A minimal sensible policy for a site without inline scripts:

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data:; frame-ancestors 'none'; base-uri 'self'

The frame-ancestors 'none' directive supersedes the obsolete X-Frame-Options and closes clickjacking.

What is no longer needed

X-XSS-Protection is obsolete: modern browsers ignore it, and in older ones it was itself a vulnerability. Feature-Policy has been renamed Permissions-Policy.

How to verify

Headers are set at several layers — CDN, reverse proxy, application — and are easily lost or duplicated when infrastructure changes. Check the actual response, not the configuration, across several URL types: the homepage, a route from the SPA router, a static file, an API endpoint. The differences between them are the most common audit finding.

And watch for regressions: a header accidentally dropped during a move to a new CDN gives no signal until it is too late.

Read next

Check how much of this is on your own site

A free scan surfaces broken links, JS errors and performance problems in about a minute.