Skip to main content
AllDevToolsHub
2026-07-29
Last reviewed: Aug 2026
SECURITY
Est Read: 12_MIN

HTTP Security Headers: The 2026 Complete Checklist

HTTP Security Headers: The 2026 Complete Checklist
Processing_Node: 01

#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:

protocol
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:

protocol
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

This logs violations without blocking anything. Run it in production for 2–4 weeks before switching to enforcement mode.


#32. Strict-Transport-Security (HSTS)

protocol
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Tells 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-age to a year, confirm that every subdomain supports HTTPS. HSTS mistakes are hard to undo, the browser will refuse HTTP for the entire max-age duration.


#33. X-Frame-Options

protocol
X-Frame-Options: DENY

Prevents 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-ancestors directive supersedes it, but X-Frame-Options is still the reliable cross-browser fallback in 2026, especially for older Safari and Firefox versions that handle frame-ancestors inconsistently. Set both.


#34. X-Content-Type-Options

protocol
X-Content-Type-Options: nosniff

Prevents 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

protocol
Referrer-Policy: strict-origin-when-cross-origin

Controls how much of the URL is included in the Referer header sent to other sites when users click links.

PolicyWhat is sent
no-referrerNothing, most private, may break analytics
no-referrer-when-downgradeFull URL to HTTPS, nothing to HTTP, old default
strict-origin-when-cross-originOrigin only on cross-origin HTTPS, full URL on same-origin, recommended
same-originFull URL same-origin, nothing cross-origin
unsafe-urlFull 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)

protocol
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):

protocol
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

protocol
X-XSS-Protection: 0

Counter-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)

protocol
Cross-Origin-Resource-Policy: same-origin

Controls 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 it
  • cross-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)

protocol
Cross-Origin-Opener-Policy: same-origin

Prevents 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)

protocol
Cross-Origin-Embedder-Policy: require-corp

Requires 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: credentialless as a less strict intermediate step.


#2Quick Reference, Header Scoring Table

HeaderPriorityValue for Most Apps
Content-Security-Policy🔴 CriticalSee nonce-based policy above
Strict-Transport-Security🔴 Criticalmax-age=31536000; includeSubDomains
X-Frame-Options🔴 CriticalDENY
X-Content-Type-Options🔴 Criticalnosniff
Referrer-Policy🟡 Highstrict-origin-when-cross-origin
Permissions-Policy🟡 Highcamera=(), microphone=(), geolocation=()
X-XSS-Protection🟡 High0 (disable old auditor)
Cross-Origin-Resource-Policy🟢 Mediumsame-origin
Cross-Origin-Opener-Policy🟢 Mediumsame-origin
Cross-Origin-Embedder-Policy🟢 Mediumrequire-corp (if needed for WASM)

#2Copy-Paste Configs

#3nginx

nginx
# 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

apache
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)

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)

typescript
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 nameValueAction
X-Frame-OptionsDENYSet
X-Content-Type-OptionsnosniffSet
Referrer-Policystrict-origin-when-cross-originSet
Permissions-Policycamera=(), microphone=(), geolocation=()Set
Strict-Transport-Securitymax-age=31536000; includeSubDomainsSet

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 includeSubDomains when 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 always directive in nginx. Without always, the add_header directive only applies to 2xx/3xx responses. Your 4xx error pages will have no security headers.
  • Setting frame-ancestors in CSP but forgetting X-Frame-Options. CSP frame-ancestors supersedes X-Frame-Options in modern browsers, but Safari ≤15 does not respect frame-ancestors. Set both.
  • Using Permissions-Policy with the old Feature-Policy syntax. The allowlist syntax changed: old geolocation 'none' is now geolocation=(). 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 headers array with source: "/(.*)" pattern
  • Total config change: 28 lines of JSON, zero application code changes

Side effects observed during testing:

  • CSP in report-only mode 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-origin broke a popup-based OAuth flow (GitHub OAuth). The fix was to set Cross-Origin-Opener-Policy: same-origin-allow-popups for the /auth/* route only.
  • Permissions-Policy with camera=(), 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

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.

RJRahul JalavadiyaFounder & Lead Engineer
Published 2026-07-29Last reviewed 2026-08-23

Tools Mentioned in This Article

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.

Last reviewed: 2026-08-23
Security Memo
AT

Rahul Jalavadiya

Engineering Protocol V1

Specializing in local-first architecture and Zero-Trust developer workflows. No data leaves the machine.