The security headers worth sending
Security headers are HTTP response headers that tell the browser to apply extra protections to your pages. A sound baseline is Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options, frame-ancestors or X-Frame-Options, Referrer-Policy, Permissions-Policy and Cross-Origin-Opener-Policy.
None of them fixes a bug in your application code. They limit what an attacker can do when something else goes wrong.
This starting set suits a site that other sites never embed. The Content-Security-Policy line only controls framing; a full policy needs its own design. If HSTS is new to your site, start with a shorter max-age, as the HSTS guide explains.
Strict-Transport-Security: max-age=31536000
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Cross-Origin-Opener-Policy: same-originWhat each header prevents
Each header targets a specific browser-side risk:
- Content-Security-Policy: limits where scripts, styles, frames and other resources can load from, which reduces the damage of cross-site scripting. It takes the most care to deploy, so it has its own guide.
- Strict-Transport-Security (HSTS): tells browsers to use only HTTPS for your domain, which blocks downgrade attacks after the first visit. The HSTS guide covers includeSubDomains and preloading.
- X-Content-Type-Options: nosniff stops browsers from guessing a file type, so an upload served as text/plain is never run as a script or applied as a stylesheet.
- Framing: the CSP frame-ancestors directive controls which sites may embed your pages, which prevents clickjacking. X-Frame-Options: DENY or SAMEORIGIN covers older browsers.
- Referrer-Policy: strict-origin-when-cross-origin sends only your origin to other sites, so paths and query strings, and any tokens in them, stay private.
- Permissions-Policy: turns off features such as the camera, microphone and geolocation for your page and its frames, so injected or third-party code can't request them.
- Cross-Origin-Opener-Policy: same-origin cuts the window reference between your page and cross-origin pages it opens or is opened by, which blocks a class of cross-window attacks. Pages that rely on cross-origin popups, such as some payment or sign-in flows, can use same-origin-allow-popups instead.
Old headers to drop
Some headers in older checklists no longer help, and one can cause harm:
- X-XSS-Protection controlled an XSS filter that browsers have since removed, and the filter could itself introduce vulnerabilities. OWASP advises leaving it out or sending X-XSS-Protection: 0, and relying on CSP instead.
- Public-Key-Pins (HPKP) was removed from browsers because a mistaken pin could lock visitors out of a site for the pin lifetime.
- Expect-CT is deprecated, because major browsers now require Certificate Transparency without it.
- Feature-Policy was replaced by Permissions-Policy, which uses a different syntax.
- X-Frame-Options: ALLOW-FROM was never widely supported. Use frame-ancestors to allow specific sites.
Rolling headers out without breaking the site
Set headers at a layer every response passes through, such as the web server, CDN or framework middleware, so error pages and redirects get them too. HTML responses need the full set; HSTS and nosniff are worth sending on everything.
Test restrictive headers in staging first. CSP, Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy can break analytics, payment widgets and sign-in popups, and Permissions-Policy can block a feature a page needs.
After deploying, check the live response, because a CDN or proxy can strip, duplicate or override headers.