---
# === IDENTITY ===
id: software/security/http-security-headers/2026
canonical_question: "What are the essential HTTP security headers?"
aliases:
  - "HTTP security headers best practices"
  - "secure HTTP response headers"
  - "HSTS Content-Security-Policy X-Frame-Options configuration"
  - "web server security headers checklist"
  - "Strict-Transport-Security header setup"
  - "Permissions-Policy header configuration"
  - "helmet.js security headers Express"
  - "nginx apache security headers"
entity_type: software_reference
domain: software > security > HTTP Security Headers
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === VERIFICATION ===
last_verified: 2026-02-27
confidence: 0.95
version: 1.0
first_published: 2026-02-27

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: stable
  last_breaking_change: "Permissions-Policy replaced Feature-Policy (2021); X-XSS-Protection deprecated -- set to 0 (2023); Expect-CT deprecated (2023)"
  next_review: 2026-08-26
  change_sensitivity: low

# === CONSTRAINTS ===
constraints:
  - "HSTS header MUST only be sent over HTTPS -- never on HTTP responses"
  - "HSTS with includeSubDomains requires ALL subdomains to support HTTPS -- misconfiguration blocks legitimate traffic"
  - "HSTS preload is irreversible in practice -- once submitted to browser preload lists, removal takes months"
  - "CSP with unsafe-inline defeats XSS protection -- use nonce-based or hash-based policies instead"
  - "X-XSS-Protection MUST be set to 0 -- the filter is deprecated and can introduce vulnerabilities in older browsers"
  - "Nginx add_header directives in inner blocks override ALL headers from outer blocks -- use include snippets"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Need Content Security Policy deep dive with nonce/hash configuration"
    use_instead: "software/security/xss-prevention/2026"
  - condition: "Need CORS configuration (Access-Control-Allow-Origin)"
    use_instead: "software/security/cors-configuration/2026"
  - condition: "Need cookie security (Secure, HttpOnly, SameSite flags)"
    use_instead: "software/security/cookie-security/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: "web_server"
    question: "What web server or framework are you using?"
    type: choice
    options: ["Nginx", "Apache", "Caddy", "Express/Node.js", "Django", "Spring Boot", "ASP.NET", "Cloudflare", "Other"]
  - key: "has_subdomains"
    question: "Does your domain have subdomains that all support HTTPS?"
    type: choice
    options: ["Yes, all subdomains use HTTPS", "No, some subdomains are HTTP-only", "Not sure"]

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/security/http-security-headers/2026"
suggested_citation: "Source: knowledgelib.io -- AI Knowledge Library (verified 2026-02-27)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "software/security/xss-prevention/2026"
      label: "XSS Prevention Guide"
  solves: []
  alternative_to: []
  often_confused_with:
    - id: "software/security/cors-configuration/2026"
      label: "CORS Configuration"
    - id: "software/security/cookie-security/2026"
      label: "Cookie Security (Secure, HttpOnly, SameSite)"

# === SOURCES (7 authoritative sources) ===
# Types: official_docs, technical_blog, rfc_spec, academic_paper, community_resource, industry_report
# Reliability: high, moderate_high, moderate, moderate_low, low, authoritative
sources:
  - id: src1
    title: "HTTP Headers Cheat Sheet"
    author: OWASP Foundation
    url: https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html
    type: community_resource
    published: 2025-01-15
    reliability: authoritative
  - id: src2
    title: "Strict-Transport-Security header"
    author: MDN Web Docs
    url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security
    type: official_docs
    published: 2025-06-01
    reliability: authoritative
  - id: src3
    title: "OWASP Secure Headers Project"
    author: OWASP Foundation
    url: https://owasp.org/www-project-secure-headers/
    type: community_resource
    published: 2026-01-25
    reliability: authoritative
  - id: src4
    title: "HTTP Observatory Tests and Scoring"
    author: MDN Web Docs
    url: https://developer.mozilla.org/en-US/observatory/docs/tests_and_scoring
    type: official_docs
    published: 2025-03-01
    reliability: high
  - id: src5
    title: "Permissions-Policy header"
    author: MDN Web Docs
    url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Permissions-Policy
    type: official_docs
    published: 2025-06-01
    reliability: authoritative
  - id: src6
    title: "Helmet.js -- Help secure Express apps with HTTP headers"
    author: Helmet.js
    url: https://helmetjs.github.io/
    type: official_docs
    published: 2025-09-01
    reliability: high
  - id: src7
    title: "NGINX Security Headers, the right way"
    author: GetPageSpeed
    url: https://www.getpagespeed.com/server-setup/nginx-security-headers-the-right-way
    type: technical_blog
    published: 2026-01-10
    reliability: moderate_high
---

# HTTP Security Headers: Essential Configuration Guide

## TL;DR

- **Bottom line**: Seven HTTP response headers form the essential security baseline -- HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, and Cross-Origin policies -- and every production site should set all of them.
- **Key tool/command**: `curl -sI https://your-site.com | grep -iE "strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy"` to audit current headers.
- **Watch out for**: Setting HSTS `includeSubDomains` when not all subdomains support HTTPS -- this locks out legitimate traffic with no easy undo.
- **Works with**: All web servers (Nginx, Apache, Caddy, IIS), all frameworks (Express/Helmet, Django, Spring Boot, ASP.NET), and all CDNs (Cloudflare, AWS CloudFront, Fastly).

## Constraints
<!-- Agents: read this section before recommending any action from this unit.
     These are hard constraints that must not be violated. -->

- HSTS header MUST only be sent over HTTPS -- never on HTTP responses
- HSTS with `includeSubDomains` requires ALL subdomains to support HTTPS -- misconfiguration blocks legitimate traffic
- HSTS `preload` is irreversible in practice -- once submitted to browser preload lists, removal takes months
- CSP with `unsafe-inline` defeats XSS protection -- use nonce-based or hash-based policies instead
- `X-XSS-Protection` MUST be set to `0` -- the filter is deprecated and can introduce vulnerabilities in older browsers
- Nginx `add_header` directives in inner blocks override ALL headers from outer blocks -- use include snippets

## Quick Reference

| # | Header | Recommended Value | Purpose | Risk if Missing |
|---|---|---|---|---|
| 1 | `Strict-Transport-Security` | `max-age=63072000; includeSubDomains; preload` | Forces HTTPS for all future connections | MITM attacks, SSL stripping, cookie hijacking |
| 2 | `Content-Security-Policy` | `default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'none'` | Controls allowed content sources | XSS attacks, data injection, clickjacking |
| 3 | `X-Content-Type-Options` | `nosniff` | Prevents MIME type sniffing | MIME confusion attacks, script injection via uploaded files |
| 4 | `X-Frame-Options` | `DENY` or `SAMEORIGIN` | Prevents clickjacking via iframes | Clickjacking, UI redressing attacks |
| 5 | `Referrer-Policy` | `strict-origin-when-cross-origin` | Controls referrer information leakage | URL token leakage, privacy exposure |
| 6 | `Permissions-Policy` | `geolocation=(), camera=(), microphone=()` | Restricts browser API access | Third-party scripts accessing sensors/camera/mic |
| 7 | `Cross-Origin-Opener-Policy` | `same-origin` | Isolates browsing context | Spectre-like side-channel attacks |
| 8 | `Cross-Origin-Resource-Policy` | `same-site` | Controls cross-origin resource loading | Data leakage via cross-origin reads |
| 9 | `Cross-Origin-Embedder-Policy` | `require-corp` | Restricts cross-origin embedding | Blocks `SharedArrayBuffer` (needed for COOP isolation) |
| 10 | `X-XSS-Protection` | `0` | Disables broken legacy XSS filter | Legacy filter can introduce new XSS vectors |

**Headers to Remove (Information Disclosure):**

| # | Header | Action | Reason |
|---|---|---|---|
| 1 | `Server` | Remove or set to generic value | Reveals web server software and version |
| 2 | `X-Powered-By` | Remove entirely | Reveals framework (Express, PHP, ASP.NET) |
| 3 | `X-AspNet-Version` | Disable in web.config | Reveals .NET version |
| 4 | `X-AspNetMvc-Version` | Disable in Global.asax | Reveals ASP.NET MVC version |

**Deprecated Headers (Do Not Use):**

| # | Header | Status | Replacement |
|---|---|---|---|
| 1 | `Expect-CT` | Deprecated | Certificate Transparency is now enforced by default |
| 2 | `Public-Key-Pins` (HPKP) | Removed from browsers | Use Certificate Transparency instead |
| 3 | `Feature-Policy` | Replaced | Use `Permissions-Policy` |
| 4 | `X-XSS-Protection` (with `1`) | Deprecated | Use CSP; set header to `0` to disable legacy filter |

## Decision Tree

```
START: What web server or framework are you using?
├── Nginx?
│   ├── YES → Use add_header in https server block; create /etc/nginx/snippets/security-headers.conf
│   └── NO ↓
├── Apache?
│   ├── YES → Enable mod_headers; use Header always set in VirtualHost or .htaccess
│   └── NO ↓
├── Caddy?
│   ├── YES → Use header directive in Caddyfile; HTTPS is automatic, add HSTS manually
│   └── NO ↓
├── Express/Node.js?
│   ├── YES → npm install helmet; app.use(helmet()) sets 11 headers with sane defaults
│   └── NO ↓
├── Django?
│   ├── YES → Configure SecurityMiddleware settings: SECURE_HSTS_SECONDS, SECURE_CONTENT_TYPE_NOSNIFF, etc.
│   └── NO ↓
├── CDN/Edge (Cloudflare, AWS)?
│   ├── YES → Configure via edge rules or transform rules; some headers set automatically
│   └── NO ↓
└── DEFAULT → Set headers at the reverse proxy level for consistent coverage across all backends
```

## Step-by-Step Guide

### 1. Audit existing security headers

Before adding headers, check what your site currently sends. Use curl or an online scanner. [src4]

```bash
# Check all security headers at once
curl -sI https://your-site.com | grep -iE \
  "strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy|x-xss-protection|cross-origin"

# Use Mozilla Observatory for a full grade
# Visit: https://developer.mozilla.org/en-US/observatory
# Or use securityheaders.com for quick scanning
```

**Verify**: You should see each header listed. Missing headers indicate gaps to address.

### 2. Set Strict-Transport-Security (HSTS)

Start with a short `max-age` (e.g., 300 seconds) and increase after confirming HTTPS works on all subdomains. [src2]

```http
# Start conservative (5 minutes)
Strict-Transport-Security: max-age=300

# After testing, ramp up to 2 years with subdomain coverage
Strict-Transport-Security: max-age=63072000; includeSubDomains

# Final: add preload after confirming at hstspreload.org
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
```

**Verify**: `curl -sI https://your-site.com | grep -i strict-transport` should show the header. Visit `https://hstspreload.org` to check preload eligibility.

### 3. Deploy Content-Security-Policy

Start in report-only mode to avoid breaking your site. Progressively tighten the policy. [src1]

```http
# Phase 1: Report-only mode (no enforcement)
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

# Phase 2: Basic enforcement
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'

# Phase 3: Strict nonce-based policy (strongest)
Content-Security-Policy: default-src 'self'; script-src 'nonce-{random}' 'strict-dynamic'; style-src 'self' 'nonce-{random}'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'
```

**Verify**: Open DevTools > Console. CSP violations appear as errors. Check `/csp-report` endpoint for violation reports.

### 4. Set remaining essential headers

These headers are straightforward and rarely cause breakage. Apply all at once. [src3]

```http
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
X-XSS-Protection: 0
Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-site
```

**Verify**: `curl -sI https://your-site.com` should show all headers. Score should be A or A+ on securityheaders.com.

### 5. Remove information disclosure headers

Strip server identification headers to reduce fingerprinting surface. [src1]

```nginx
# Nginx: hide server version
server_tokens off;

# Express: Helmet removes X-Powered-By automatically
# Or manually: app.disable('x-powered-by');
```

**Verify**: `curl -sI https://your-site.com | grep -iE "server:|x-powered-by"` should show no version info.

## Code Examples

### Express/Node.js: Helmet.js (recommended)

> Full script: [express-node-js-helmet-js-recommended.js](scripts/express-node-js-helmet-js-recommended.js) (32 lines)

```javascript
// Input:  Express app without security headers
// Output: Express app with 11 security headers set
const express = require('express');     // ^4.18.0
const helmet = require('helmet');       // ^8.0.0
const app = express();
# ... (see full script)
```

### Django: SecurityMiddleware Settings

```python
# settings.py -- Django SecurityMiddleware handles most headers
# Ensure 'django.middleware.security.SecurityMiddleware' is in MIDDLEWARE

# HSTS (only active when HTTPS is used)
SECURE_HSTS_SECONDS = 63072000           # 2 years
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

# Other security headers
SECURE_CONTENT_TYPE_NOSNIFF = True       # X-Content-Type-Options: nosniff
SECURE_BROWSER_XSS_FILTER = False        # X-XSS-Protection: 0 (Django 4.1+)
X_FRAME_OPTIONS = 'DENY'                 # X-Frame-Options: DENY
SECURE_REFERRER_POLICY = 'strict-origin-when-cross-origin'

# HTTPS redirect
SECURE_SSL_REDIRECT = True
SECURE_REDIRECT_EXEMPT = []              # URL patterns exempt from redirect

# CSP: use django-csp package
# pip install django-csp
# MIDDLEWARE += ['csp.middleware.CSPMiddleware']
# CSP_DEFAULT_SRC = ("'self'",)
# CSP_SCRIPT_SRC = ("'self'",)
# CSP_OBJECT_SRC = ("'none'",)
```

### Nginx: Security Headers Snippet

```nginx
# /etc/nginx/snippets/security-headers.conf
# Include this in each server block: include snippets/security-headers.conf;

# HSTS -- only on HTTPS server blocks
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

# Content Security Policy
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'" always;

# Prevent MIME sniffing
add_header X-Content-Type-Options "nosniff" always;

# Clickjacking protection
add_header X-Frame-Options "DENY" always;

# Referrer control
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Disable legacy XSS filter
add_header X-XSS-Protection "0" always;

# Restrict browser features
add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=()" always;

# Cross-origin isolation
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Resource-Policy "same-site" always;

# Hide server version
server_tokens off;
```

### Apache: VirtualHost Configuration

```apache
# Enable mod_headers: a2enmod headers
# Add to VirtualHost :443 block or .htaccess

# HSTS
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

# CSP
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'"

# Prevent MIME sniffing
Header always set X-Content-Type-Options "nosniff"

# Clickjacking protection
Header always set X-Frame-Options "DENY"

# Referrer control
Header always set Referrer-Policy "strict-origin-when-cross-origin"

# Disable legacy XSS filter
Header always set X-XSS-Protection "0"

# Restrict browser features
Header always set Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=()"

# Cross-origin isolation
Header always set Cross-Origin-Opener-Policy "same-origin"
Header always set Cross-Origin-Resource-Policy "same-site"

# Remove server info
Header always unset X-Powered-By
ServerTokens Prod
ServerSignature Off
```

### Caddy: Caddyfile Configuration

```caddy
# Caddyfile -- Caddy handles HTTPS automatically
# Security headers must be added manually

(security-headers) {
    header {
        Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
        Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Referrer-Policy "strict-origin-when-cross-origin"
        X-XSS-Protection "0"
        Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=()"
        Cross-Origin-Opener-Policy "same-origin"
        Cross-Origin-Resource-Policy "same-site"
        -Server
    }
}

example.com {
    import security-headers
    root * /var/www/html
    file_server
}
```

## Anti-Patterns

### Wrong: Setting HSTS on HTTP responses

```nginx
# BAD -- HSTS on port 80 is ignored by browsers and wastes bytes
server {
    listen 80;
    add_header Strict-Transport-Security "max-age=63072000" always;
}
```

### Correct: HSTS only on HTTPS

```nginx
# GOOD -- HSTS on HTTPS only; HTTP redirects to HTTPS
server {
    listen 80;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
}
```

### Wrong: CSP with unsafe-inline

```http
# BAD -- unsafe-inline allows injected scripts to execute, defeating CSP
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
```

### Correct: Nonce-based CSP

```http
# GOOD -- only scripts with matching nonce execute
Content-Security-Policy: default-src 'self'; script-src 'nonce-abc123def456' 'strict-dynamic'
```

### Wrong: X-XSS-Protection set to 1

```http
# BAD -- the legacy XSS filter can be abused to selectively disable scripts
X-XSS-Protection: 1; mode=block
```

### Correct: X-XSS-Protection disabled

```http
# GOOD -- disable legacy filter; rely on CSP for XSS protection
X-XSS-Protection: 0
```

### Wrong: Nginx headers in location blocks override server block headers

```nginx
# BAD -- adding a header in a location block silently drops ALL server-level headers
server {
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;

    location /api {
        add_header Cache-Control "no-store";
        # X-Frame-Options and X-Content-Type-Options are now GONE for /api
    }
}
```

### Correct: Use include snippet for consistent headers

```nginx
# GOOD -- snippet ensures all headers are present in every context
server {
    include snippets/security-headers.conf;

    location /api {
        include snippets/security-headers.conf;
        add_header Cache-Control "no-store";
    }
}
```

### Wrong: HSTS preload without testing

```http
# BAD -- submitting to preload list before verifying all subdomains use HTTPS
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
# If dev.example.com or staging.example.com don't have HTTPS, they become unreachable
```

### Correct: Gradual HSTS rollout

```http
# GOOD -- start small, verify, then increase
# Week 1: 5-minute max-age, no subdomains
Strict-Transport-Security: max-age=300
# Week 2: 1-day max-age with subdomains
Strict-Transport-Security: max-age=86400; includeSubDomains
# Month 2: full 2-year max-age
Strict-Transport-Security: max-age=63072000; includeSubDomains
# Month 3+: add preload after verifying at hstspreload.org
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
```

## Common Pitfalls

- **HSTS locks out subdomains**: Setting `includeSubDomains` when `dev.example.com` or `staging.example.com` don't have valid HTTPS certificates makes them unreachable. Fix: Audit all subdomains for HTTPS support before enabling `includeSubDomains`. [src2]
- **Nginx header inheritance broken**: Adding any `add_header` directive in a `location` block silently drops all `add_header` directives from the parent `server` block. Fix: Use an `include` snippet with all security headers in every block that adds headers. [src7]
- **CSP breaks inline scripts**: Deploying a strict CSP without auditing inline `<script>` tags and event handlers breaks site functionality. Fix: Start with `Content-Security-Policy-Report-Only` and review violation reports before enforcing. [src1]
- **Permissions-Policy syntax confusion**: The old `Feature-Policy` header used space-separated values (`geolocation 'none'`), but `Permissions-Policy` uses `=()` syntax (`geolocation=()`). Mixing formats silently fails. Fix: Use only `Permissions-Policy` with the new syntax. [src5]
- **Missing `always` parameter in Nginx**: Without `always`, Nginx only adds headers on 2xx/3xx responses. Error pages (4xx/5xx) are sent without security headers. Fix: Always use `add_header ... always;`. [src7]
- **HSTS on HTTP port**: Setting HSTS on port 80 has no effect -- browsers only process HSTS headers received over HTTPS. Fix: Configure HSTS only in the HTTPS server block. [src2]
- **Double headers from proxy and backend**: Both the reverse proxy (Nginx) and the backend (Express/Helmet) set the same headers, causing duplicate values. Fix: Set headers at one layer only -- preferably the reverse proxy for consistency. [src6]
- **X-Frame-Options vs CSP frame-ancestors**: `X-Frame-Options` only supports `DENY` and `SAMEORIGIN`. For granular control (specific allowed origins), use CSP `frame-ancestors`. Both can coexist, but CSP takes precedence in modern browsers. Fix: Use CSP `frame-ancestors` for new deployments; keep `X-Frame-Options` for legacy browser support. [src1]

## Diagnostic Commands

```bash
# Audit all security headers of a site
curl -sI https://your-site.com | grep -iE \
  "strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy|x-xss-protection|cross-origin|x-powered-by|server:"

# Check HSTS preload eligibility
# Visit: https://hstspreload.org/?domain=your-site.com

# Scan with Mozilla Observatory (online)
# Visit: https://developer.mozilla.org/en-US/observatory

# Scan with securityheaders.com (online)
# Visit: https://securityheaders.com/?q=your-site.com

# Validate CSP policy
# Visit: https://csp-evaluator.withgoogle.com/

# Check if HSTS is cached in browser (Chrome)
# Visit: chrome://net-internals/#hsts
# Query domain to see cached HSTS status

# Test CSP in report-only mode (add header, check console)
# Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

# Verify Nginx config before reload
nginx -t && nginx -s reload

# Check Apache modules loaded (need mod_headers)
apachectl -M | grep headers
```

## Version History & Compatibility

| Header/Standard | Status | Browser Support | Key Changes |
|---|---|---|---|
| Strict-Transport-Security | RFC 6797 (2012) | All modern browsers | Stable since 2012; preload lists maintained by Chrome, Firefox, Safari, Edge |
| Content-Security-Policy L3 | W3C CR | Chrome 59+, Firefox 58+, Safari 15.4+, Edge 79+ | `strict-dynamic`, `report-to` (replaces `report-uri`) |
| X-Content-Type-Options | Standard | All modern browsers | Stable; `nosniff` is the only valid value |
| X-Frame-Options | RFC 7034 (2013) | All modern browsers | Being superseded by CSP `frame-ancestors`; `ALLOW-FROM` never had full support |
| Referrer-Policy | W3C CR | All modern browsers | `strict-origin-when-cross-origin` is the browser default since 2021 |
| Permissions-Policy | W3C Draft | Chrome 88+, Firefox 74+, Safari 16+, Edge 88+ | Replaced `Feature-Policy`; different header syntax |
| Cross-Origin-Opener-Policy | Standard | Chrome 83+, Firefox 79+, Safari 15.2+, Edge 83+ | Required for `SharedArrayBuffer` access |
| Cross-Origin-Resource-Policy | Standard | Chrome 73+, Firefox 74+, Safari 12+, Edge 79+ | Defends against Spectre-like attacks |

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Any production website or API | Local development server (HSTS will block HTTP) | Skip HSTS in dev; use other headers |
| Site serves user-generated content | Static site with zero dynamic content and no subresources | Minimal CSP (`default-src 'none'`) suffices |
| Multiple subdomains all on HTTPS | Some subdomains are HTTP-only or use self-signed certs | Omit `includeSubDomains` from HSTS |
| Embedding third-party content (ads, widgets) | Site is a public embeddable widget itself | Set `X-Frame-Options: SAMEORIGIN` or CSP `frame-ancestors` with specific origins |
| API endpoints returning JSON | WebSocket-only server | CORS headers matter more; security headers still recommended |

## Important Caveats

- HSTS `preload` submits your domain to a hardcoded list in all major browsers -- if you later need to serve HTTP, you cannot easily undo this. Test thoroughly before adding `preload`
- CSP `report-uri` is deprecated in favor of `report-to` (Reporting API), but `report-to` is not yet supported in all browsers. Use both during the transition period
- `Permissions-Policy` is still a W3C Draft and the available directives change between browser versions -- check MDN for current support before relying on specific features
- `Cross-Origin-Embedder-Policy: require-corp` breaks loading of cross-origin resources (images, scripts, fonts) that don't set `Cross-Origin-Resource-Policy` -- audit third-party resources before enabling
- The `Server` header cannot always be fully removed (some web servers add it after application-level headers) -- minimize rather than rely on complete removal
- Security headers at the CDN/edge level may override or duplicate headers set by the origin server -- configure headers at one layer only

## Related Units
<!-- Generated from related_kos frontmatter -->

- [XSS Prevention Guide](/software/security/xss-prevention/2026)
- [CORS Configuration](/software/security/cors-configuration/2026)
- [Cookie Security](/software/security/cookie-security/2026)
