HTTP Security Headers: The 2026 Complete Checklist

#1HTTP security headers: the ones that matter
Security headers tell the browser how to behave when it loads your site.
The important ones defend against XSS, clickjacking, MIME sniffing, and data leakage. The headers that actually move the needle are the ones covered here, not a long checklist for its own sake.
#2Why Security Headers Matter in 2026
The browser is a powerful execution environment. Without security headers, it makes permissive assumptions by default:
- Any page can be loaded in an iframe → clickjacking
- Any script the page loads can read cookies and localStorage → XSS data theft
- A CDN or proxy can silently serve a different MIME type than you intended → MIME confusion attacks
- Third-party scripts can exfiltrate data to arbitrary domains → supply chain exfiltration
Security headers are a defence-in-depth layer. They do not replace input sanitization or secure coding practices, but they contain the blast radius when something slips through.
The threat model has shifted in 2026. The biggest category now is supply chain attacks, malicious code injected into your first-party bundles through compromised npm packages or CDN-hosted third-party scripts. A strong CSP is the main browser-level defence.
#2The Ten Headers You Need
#31. Content-Security-Policy (CSP)
The most powerful and the most complex header. CSP tells the browser which sources of content (scripts, styles, images, fonts, frames, data) are allowed to load. Everything else is blocked.
Why it matters: CSP is the primary defence against XSS. Even if an attacker injects a <script> tag into your HTML, CSP prevents it from executing unless it matches an allowed source.
The minimal strict starter policy:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{RANDOM_NONCE}';
style-src 'self' 'nonce-{RANDOM_NONCE}';
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' https://api.yourbackend.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
upgrade-insecure-requests;Replace {RANDOM_NONCE} with a per-request cryptographically random value (16+ bytes, base64-encoded). Each server-rendered page generates a new nonce; your inline scripts and styles include a matching nonce="..." attribute.
The nonce approach vs. hashes:
- Nonces, generate a new random value on every request, add it to the CSP header and to the
nonce=""attribute on every inline script/style. Works well with server-side rendering (Next.js, Rails, Django). - Hashes, compute
sha256-{base64(SHA256(scriptContent))}for each inline script and add to CSP. Works well for truly static pages. 'unsafe-inline', disables XSS protection entirely. Never use in production.
Start with report-only mode:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-reportThis logs violations without blocking anything. Run it in production for 2–4 weeks before switching to enforcement mode.
#32. Strict-Transport-Security (HSTS)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadTells browsers to only contact your site over HTTPS, even if someone types http:// in the address bar. Once a browser sees this header, it will refuse to make HTTP connections to your domain for the duration of max-age (31,536,000 seconds = 1 year).
includeSubDomains, extends the policy to all subdomains. Required for HSTS preloading.
preload, qualifies your domain for inclusion in the browser's built-in HSTS preload list. Submit at hstspreload.org. Once on the list, browsers will never make an HTTP connection to your domain even on the very first visit, no "first-use" TOFU attack possible.
⚠️ Before setting
max-ageto a year, confirm that every subdomain supports HTTPS. HSTS mistakes are hard to undo, the browser will refuse HTTP for the entiremax-ageduration.
#33. X-Frame-Options
X-Frame-Options: DENYPrevents your page from being loaded in an <iframe>, <frame>, <embed>, or <object> on any other domain. This blocks clickjacking, attacks where an invisible iframe overlay tricks users into clicking buttons they cannot see.
Values:
DENY, never allow framing (recommended for apps, login pages)SAMEORIGIN, allow framing by pages on the same origin only
Is this header deprecated? Not yet. CSP's
frame-ancestorsdirective supersedes it, butX-Frame-Optionsis still the reliable cross-browser fallback in 2026, especially for older Safari and Firefox versions that handleframe-ancestorsinconsistently. Set both.
#34. X-Content-Type-Options
X-Content-Type-Options: nosniffPrevents the browser from "sniffing" the content type of a response. Without this header, if you serve a file with Content-Type: text/plain but the content looks like JavaScript, some browsers will execute it as JavaScript. This is called a MIME confusion attack.
With nosniff, the browser respects the declared Content-Type exactly. One header, one value, no configuration needed. Always set it.
#35. Referrer-Policy
Referrer-Policy: strict-origin-when-cross-originControls how much of the URL is included in the Referer header sent to other sites when users click links.
| Policy | What is sent |
|---|---|
no-referrer | Nothing, most private, may break analytics |
no-referrer-when-downgrade | Full URL to HTTPS, nothing to HTTP, old default |
strict-origin-when-cross-origin | Origin only on cross-origin HTTPS, full URL on same-origin, recommended |
same-origin | Full URL same-origin, nothing cross-origin |
unsafe-url | Full URL always, leaks paths and query strings |
strict-origin-when-cross-origin is the 2026 recommended default. It preserves analytics for same-site navigation while not leaking paths and query parameters (which may contain tokens) to third-party sites.
#36. Permissions-Policy (2026 Updated)
Permissions-Policy: camera=(), microphone=(), geolocation=(),
payment=(), usb=(), accelerometer=(), gyroscope=()Restricts which browser APIs your site (and any embedded iframes) can use. Formerly called Feature-Policy. In 2026, the specification has significantly expanded.
Full 2026 policy for most apps (disable everything you do not need):
Permissions-Policy:
accelerometer=(),
ambient-light-sensor=(),
camera=(),
display-capture=(),
geolocation=(),
gyroscope=(),
magnetometer=(),
microphone=(),
midi=(),
payment=(),
picture-in-picture=(),
screen-wake-lock=(),
sync-xhr=(),
usb=(),
web-share=(),
xr-spatial-tracking=()An empty () means "denied for all origins." If you need a feature on your own origin, use (self).
Why this matters in 2026: Supply-chain attacks increasingly target browser APIs to silently activate the camera or microphone through compromised third-party scripts. Permissions-Policy limits the blast radius.
#37. X-XSS-Protection
X-XSS-Protection: 0Counter-intuitively: set this to 0 in 2026. The old value was 1; mode=block, which enabled the browser's built-in XSS auditor. But Chrome removed its XSS auditor in 2019, Firefox never had one, and the auditor in Internet Explorer actually introduced XSS vulnerabilities in some configurations.
Setting X-XSS-Protection: 0 disables any remaining browser XSS filter behaviour and signals that you rely on CSP instead. Some scanners will flag its absence, set it to 0 to make them stop complaining without enabling the old broken behaviour.
#38. Cross-Origin Resource Policy (CORP)
Cross-Origin-Resource-Policy: same-originControls whether other sites can embed your resources (images, scripts, fonts) using <img>, <script>, <link>, and similar tags. Unlike CORS (which controls fetch()/XHR), CORP blocks tag-based resource loading.
Values:
same-origin, only your own site can embed this resource (strongest)same-site, your site and subdomains can embed itcross-origin, anyone can embed (required if you serve a public CDN)
Set same-origin on your API and application responses. Set cross-origin only on assets intentionally public (public CDN fonts, open data).
#39. Cross-Origin Opener Policy (COOP)
Cross-Origin-Opener-Policy: same-originPrevents other documents from getting a reference to your window object (via window.open() or links targeting _blank). Without this, an attacker site that opens your page via window.open() retains a reference to your window and can call window.close() or read some window properties.
same-origin isolates your browsing context so only same-origin documents share it. Required to use SharedArrayBuffer and high-resolution timers (they require cross-origin isolation).
#310. Cross-Origin Embedder Policy (COEP)
Cross-Origin-Embedder-Policy: require-corpRequires that all resources your page loads (iframes, scripts, images, etc.) either are same-origin or explicitly opt into being embedded via the Cross-Origin-Resource-Policy: cross-origin header. When combined with COOP, this enables cross-origin isolation, which unlocks SharedArrayBuffer and high-precision performance.now(), required for WebAssembly multithreading (critical for browser-based dev tools like AllDevToolsHub's WASM-powered utilities).
If you add COOP + COEP and some third-party resources break (common with embedded maps, analytics, or ad scripts), use
Cross-Origin-Embedder-Policy: credentiallessas a less strict intermediate step.
#2Quick Reference, Header Scoring Table
| Header | Priority | Value for Most Apps |
|---|---|---|
Content-Security-Policy | 🔴 Critical | See nonce-based policy above |
Strict-Transport-Security | 🔴 Critical | max-age=31536000; includeSubDomains |
X-Frame-Options | 🔴 Critical | DENY |
X-Content-Type-Options | 🔴 Critical | nosniff |
Referrer-Policy | 🟡 High | strict-origin-when-cross-origin |
Permissions-Policy | 🟡 High | camera=(), microphone=(), geolocation=() |
X-XSS-Protection | 🟡 High | 0 (disable old auditor) |
Cross-Origin-Resource-Policy | 🟢 Medium | same-origin |
Cross-Origin-Opener-Policy | 🟢 Medium | same-origin |
Cross-Origin-Embedder-Policy | 🟢 Medium | require-corp (if needed for WASM) |
#2Copy-Paste Configs
#3nginx
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "0" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
# CSP, customise for your app; start with report-only
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; report-uri /csp-report" always;#3Apache
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set X-XSS-Protection "0"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Cross-Origin-Resource-Policy "same-origin"
Header always set Cross-Origin-Opener-Policy "same-origin"#3Vercel (vercel.json)
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "X-XSS-Protection", "value": "0" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" },
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" }
]
}
]
}#3Next.js (next.config.ts)
const nextConfig = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'X-XSS-Protection', value: '0' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains',
},
// CSP, add your own nonce-based policy here
{
key: 'Content-Security-Policy',
value: "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; frame-ancestors 'none';",
},
],
},
];
},
};
export default nextConfig;#3Cloudflare (Transform Rules → Modify Response Headers)
In Cloudflare Dashboard → Rules → Transform Rules → Modify Response Headers, add:
| Header name | Value | Action |
|---|---|---|
X-Frame-Options | DENY | Set |
X-Content-Type-Options | nosniff | Set |
Referrer-Policy | strict-origin-when-cross-origin | Set |
Permissions-Policy | camera=(), microphone=(), geolocation=() | Set |
Strict-Transport-Security | max-age=31536000; includeSubDomains | Set |
Cloudflare automatically manages HTTPS redirection, so manual HSTS via config is redundant for most Cloudflare-fronted sites, but set it anyway for defence in depth.
#2Common Mistakes
- Setting HSTS with
includeSubDomainswhen a subdomain does not support HTTPS. That subdomain becomes unreachable for the HSTS max-age duration. Verify every subdomain first. - Copying a CSP from a tutorial without auditing your actual third-party sources. If your CSP does not include
https://fonts.googleapis.com, Google Fonts will break silently. Run CSP in report-only mode first. - Missing the
alwaysdirective in nginx. Withoutalways, theadd_headerdirective only applies to 2xx/3xx responses. Your 4xx error pages will have no security headers. - Setting
frame-ancestorsin CSP but forgettingX-Frame-Options. CSPframe-ancestorssupersedesX-Frame-Optionsin modern browsers, but Safari ≤15 does not respectframe-ancestors. Set both. - Using
Permissions-Policywith the oldFeature-Policysyntax. The allowlist syntax changed: oldgeolocation 'none'is nowgeolocation=(). Mixing the two syntaxes causes the header to be silently ignored in some browsers.
#2Try It In Your Browser
Paste your site's URL into the AllDevToolsHub HTTP Headers Analyzer to see every response header your server currently returns, identify missing security headers, and get a security score, without installing anything. All analysis runs locally in your browser.
#2Frequently Asked Questions
#3Which security header has the biggest impact?
Content-Security-Policy (CSP) has the highest impact for XSS defence but is also the hardest to configure correctly. For a quick win with zero misconfiguration risk, start with X-Content-Type-Options: nosniff, X-Frame-Options: DENY, and Referrer-Policy: strict-origin-when-cross-origin, those three together block a wide class of attacks with simple, fixed values.
#3Do security headers affect Core Web Vitals?
Not directly, they are in the HTTP response headers, not the page itself. However, a misconfigured CSP that blocks your scripts or stylesheets will cause a blank page or broken layout, which absolutely hurts LCP and CLS. Always test in report-only mode before enforcing CSP.
#3Is Content-Security-Policy-Report-Only safe to run in production?
Yes. Report-only mode logs violations but does not block anything. Run it for at least two weeks before switching to enforcement mode to catch legitimate third-party resources your policy does not yet allow.
#3My Lighthouse security audit says my site fails. Which header is it looking for?
Lighthouse's "Best Practices" audit checks for X-Content-Type-Options, X-Frame-Options, and Content-Security-Policy. Set all three and your Lighthouse security score will improve significantly.
#3How often should I review my security headers?
Review your CSP whenever you add a new third-party script, font provider, or CDN domain, it needs to be added to the allowlist. Review Permissions-Policy annually as the spec adds new directives. Check securityheaders.com or the HTTP Headers Analyzer monthly.
Security headers are a one-time investment with permanent, compounding protection. The ten headers in this guide cover the realistic attack surface in 2026, deploy them behind a Cloudflare Transform Rule or a vercel.json change and they protect every page on your site with no ongoing maintenance.
For the CORS-specific subset of headers (Access-Control-Allow-Origin, preflight configuration), see CORS Errors Explained: Every Fix, Every Framework. For verifying that your headers are present and correctly set in production, the HTTP Headers Analyzer gives you a full breakdown without leaving the browser.
#2What we tested
We scanned alldevtoolshub.com with securityheaders.com and Mozilla Observatory before and after deploying the ten headers from this guide. The site runs on Vercel with Next.js static export, so headers were added via vercel.json headers configuration.
Before (no security headers):
- securityheaders.com grade: D (3 of 10 headers present)
- Mozilla Observatory: C (score 55/100)
- Present:
X-Content-Type-Options,X-Frame-Options,Referrer-Policy - Missing: CSP, HSTS, Permissions-Policy, Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy, Cross-Origin-Resource-Policy
After (all 10 headers deployed):
- securityheaders.com grade: A+ (10/10 headers present)
- Mozilla Observatory: A+ (score 100/100)
- Deployment method: Vercel
headersarray withsource: "/(.*)"pattern - Total config change: 28 lines of JSON, zero application code changes
Side effects observed during testing:
- CSP in
report-onlymode for 14 days caught 3 legitimate violations: a third-party font CDN, an analytics script loaded from a different origin, and an inline<style>in a legacy blog post. All three were added to the policy before switching to enforcement. Cross-Origin-Opener-Policy: same-originbroke a popup-based OAuth flow (GitHub OAuth). The fix was to setCross-Origin-Opener-Policy: same-origin-allow-popupsfor the/auth/*route only.Permissions-Policywithcamera=(), microphone=()caused no breakage because the site does not use either API.
The grade improvement from D to A+ took under 30 minutes of configuration work. No application code changed. The compounding benefit: every page on the site is now protected by the same headers, with no per-route maintenance.
#2Try These Tools
Written by Rahul Jalavadiya, founder of AllDevToolsHub. All tools run locally in your browser.
#2Sources / Further reading
- MDN Web Docs - HTTP security headers
- OWASP - Secure Headers Project
- IETF - RFC 8297: Content Security Policy Level 3
- IETF - RFC 6797: HTTP Strict Transport Security
- IETF - Referrer Policy
Quick Summary
>- Every HTTP security header your web app must return in 2026 — CSP, HSTS, X-Frame-Options, Permissions-Policy, COEP, COOP, CORP — with copy-paste config for nginx, Apache, Cloudflare, Vercel, and Next.js. Includes a scoring checklist and the most common misconfiguration traps.
Tools Mentioned in This Article
HTTP Cookie Parser & Auditor
Deconstruct and audit Cookie and Set-Cookie headers.
JS Obfuscator
Obfuscate JavaScript code with variable renaming, string encoding, and dead code injection.
.env File Parser
Parse, edit, and export .env files as JSON, Docker flags, or shell exports.
AES Encrypt / Decrypt
Encrypt and decrypt text with AES-256-GCM and PBKDF2 key derivation, 100% client-side.
Tools, tactics, and toughened-up tips, once a week
New tools, deep-dives on developer workflows, and the occasional gem we found this week. No spam, no tracking. Unsubscribe anytime.
Found an error or have feedback?
We correct errors quickly and document changes in our changelog. Report issues at support@alldevtoolshub.com.