The Essential Seven HTTP Security Headers
HTTP Security Headers are server response directives that instruct web browsers to activate built-in defensive security protections.
Complete HTTP Security Headers Reference Matrix
| HTTP Security Header | Recommended Production Directive | Key Defensive Purpose | Obsoleted / Deprecated Alternative |
|---|---|---|---|
| Content-Security-Policy (CSP) | default-src 'self'; script-src 'self' 'nonce-...'; object-src 'none'; | Mitigates XSS, data injection, and clickjacking | Replaces X-XSS-Protection |
| Strict-Transport-Security (HSTS) | max-age=63072000; includeSubDomains; preload | Enforces HTTPS; blocks SSL-stripping MITM | Replaces insecure HTTP redirects |
| X-Content-Type-Options | nosniff | Prevents MIME-sniffing attacks on uploads | Mandatory for all web assets |
| X-Frame-Options | DENY or SAMEORIGIN | Defends against Clickjacking framing attacks | Superseeded by CSP frame-ancestors |
| Permissions-Policy | camera=(), microphone=(), geolocation=() | Disables unnecessary hardware APIs | Replaces deprecated Feature-Policy |
| Referrer-Policy | strict-origin-when-cross-origin | Prevents URL path & token leakage in Referer header | Obsoletes default browser leaks |
| Cross-Origin-Opener-Policy (COOP) | same-origin | Isolates browsing context (Spectre mitigation) | Required for SharedArrayBuffer |
| Cross-Origin-Embedder-Policy (COEP) | require-corp | Enforces cross-origin resource permissions | Works with COOP for complete isolation |
Every production web application should implement the following seven foundational headers:
- Strict-Transport-Security (HSTS): Enforces HTTPS and prevents SSL-stripping MITM attacks.
- Content-Security-Policy (CSP): Restricts origins for scripts, styles, images, and child frames.
- X-Frame-Options: Prevents clickjacking by restricting iframe embedding.
- X-Content-Type-Options: Prevents MIME sniffing by forcing the browser to adhere strictly to declared
Content-Type. - Referrer-Policy: Protects visitor privacy by restricting referrer URLs sent to third parties.
- Permissions-Policy: Restricts browser hardware features (camera, microphone, geolocation).
- Cross-Origin-Opener-Policy (COOP): Isolates top-level browsing contexts to defend against Spectre-style side-channel attacks.
HTTP Strict Transport Security (HSTS): Directives & Preload
HSTS informs browsers that an application must ONLY be accessed over HTTPS. Even if a user types http://example.com or follows an unencrypted link, the browser automatically rewrites the request to HTTPS locally before dispatching traffic.
Syntax & Directives
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadmax-age=31536000: Enforces HTTPS for one year (in seconds).includeSubDomains: Applies policy to all existing and future subdomains.preload: Authorizes submission to the official Chrome HSTS preload list (baked directly into major browsers).
Preloading Warning: Submitting to the HSTS preload list is permanent and irreversible for months. Ensure all subdomains (including legacy internal tools) support valid SSL certificates before adding preload.
Content-Security-Policy (CSP Level 3): Building a Strict Baseline
A Content Security Policy defines an allowlist of trusted sources for content loaded by the browser. A modern strict CSP uses cryptographic request nonces rather than brittle domain allowlists:
Content-Security-Policy: \
default-src 'self'; \
script-src 'self' 'nonce-randomNonce123' 'strict-dynamic'; \
style-src 'self' 'unsafe-inline'; \
img-src 'self' data: https:; \
font-src 'self' https://fonts.gstatic.com; \
connect-src 'self' https://api.wesecurex.com; \
frame-ancestors 'none'; \
object-src 'none'; \
base-uri 'none';frame-ancestors 'none': SupersedesX-Frame-Options: DENYin modern browsers.object-src 'none': Disables dangerous legacy plugins (Flash, Java Applets).base-uri 'none': Prevents attackers from injecting<base>tags to hijack relative URLs.
Clickjacking Defense & MIME-Type Hardening
X-Frame-Options
Clickjacking tricks users into clicking transparent iframe layers positioned over benign buttons. To prevent framing:
X-Frame-Options: DENY
# Or allow framing only by your own origin:
X-Frame-Options: SAMEORIGINX-Content-Type-Options
Web browsers historically attempted to guess ('sniff') the MIME type of a file if the server header was missing or generic (text/plain), sometimes executing image uploads containing malicious HTML. To block this behavior:
X-Content-Type-Options: nosniffPermissions-Policy & Referrer-Policy
Permissions-Policy (Formerly Feature-Policy)
Explicitly disables access to sensitive device APIs that your web application does not need:
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()Referrer-Policy
Controls how much URL information is sent in the Referer header when visitors navigate away:
Referrer-Policy: strict-origin-when-cross-originSends full path to same-origin requests, but only sends the domain (https://example.com/) on cross-origin requests, protecting query parameters containing sensitive tokens.
Battle-Tested Production Configurations
Below are production-grade configurations for modern web servers:
# Nginx Configuration (/etc/nginx/conf.d/security_headers.conf)
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 Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; script-src 'self'; object-src 'none';" always;Next.js Security Headers Configuration
In Next.js applications, configure headers directly in next.config.js or next.config.ts:
// next.config.js
const securityHeaders = [
{ key: 'X-DNS-Prefetch-Control', value: 'on' },
{ key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
];
module.exports = {
async headers() {
return [{ source: '/:path*', headers: securityHeaders }];
},
};Permissions-Policy & Cross-Origin Isolation (COOP / COEP)
Modern Permissions-Policy Syntax
The Permissions-Policy header allows web developers to disable invasive browser APIs that your application does not require, preventing rogue third-party advertising scripts or XSS payloads from activating hardware sensors:
# Disable camera, microphone, geolocation, and payment request APIs
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;Cross-Origin Isolation for Spectre Defense
Modern web browsers require cross-origin isolation before unlocking high-resolution performance timers (performance.now() with sub-millisecond precision) or SharedArrayBuffer to prevent CPU side-channel timing attacks (Spectre). Deploy paired headers:
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;Audit your live HTTP security headers and detect missing directives using the Wescequre Security Scanner.
Common Mistakes to Avoid
❌Adding the 'preload' directive to HSTS without auditing all subdomains
Why it happens: Teams copy-paste recommended HSTS snippets without testing internal subdomains.
Why it matters: If an internal subdomain (e.g., `staging.corp.example.com` or `vpn.example.com`) does not have a valid SSL certificate, it becomes completely inaccessible across all preloaded browsers.
Correct approach: Test with `max-age=300` first, verify all subdomains, increase to 1 year, and only add `preload` after multi-month verification.
❌Using `add_header` in Nginx child blocks without understanding inheritance
Why it happens: In Nginx, defining `add_header` in a `location` block wipes out all `add_header` directives defined in the parent `server` block.
Why it matters: Security headers disappear on API routes or static asset paths where child `location` blocks are defined.
Correct approach: Use an include file (`include /etc/nginx/security-headers.conf;`) inside every location block that defines custom headers.
❌Configuring CSP with `default-src *` or `unsafe-inline`
Why it happens: Developers add permissive wildcards to clear console errors quickly.
Why it matters: Permissive CSP directives completely negate the security protection against cross-site scripting.
Correct approach: Use CSP report-only mode (`Content-Security-Policy-Report-Only`) to discover required assets before enforcing strict policies.
Troubleshooting Guide
Problem: Security headers scanner reports missing headers, but they are defined in Nginx config
Possible Causes:
- Nginx `add_header` directive omitted the `always` parameter, causing headers to be omitted on 4xx and 5xx error responses.
How to verify: Check response headers on a 404 page: `curl -I https://example.com/nonexistent`.
How to fix: Append `always` to every Nginx `add_header` directive (e.g., `add_header X-Frame-Options DENY always;`).
Problem: Web fonts from Google Fonts fail to load after enabling CSP
Possible Causes:
- CSP blocked font stylesheets from `fonts.googleapis.com` or font binary files from `fonts.gstatic.com`.
How to verify: Check browser console for 'Refused to load the font...'.
How to fix: Add `https://fonts.googleapis.com` to `style-src` and `https://fonts.gstatic.com` to `font-src`.
Actionable Checklist
Wescequre Platform · Scanner Engine
Automated Vulnerability Scanner
Launch targeted or full-domain security audits to detect OWASP Top 10 vulnerabilities automatically.
Includes: OWASP Top 10 automated test suites · Real-time severity scoring (CVSS v3.1) · Instant remediation code snippets
Frequently Asked Questions
`X-Frame-Options` is a legacy header supporting `DENY` and `SAMEORIGIN`. `frame-ancestors` is part of Content Security Policy Level 2/3 and supports fine-grained domain lists. When both are present, modern browsers prioritize `frame-ancestors`.
The `Content-Security-Policy-Report-Only` header evaluates your policy without blocking any content. Violations are logged to a designated reporting endpoint (`report-uri` or `report-to`), allowing teams to fix broken assets before enforcing the policy.
Security headers have zero negative impact on performance (adding fewer than 500 bytes to response headers). HSTS positively impacts SEO because Google Search favors secure, HTTPS-enforced domains.
Authoritative Sources & References
- OWASP Secure Headers ProjectOWASP Foundation (official)View Source
- MDN Web Docs: HTTP Headers ReferenceMozilla (technical)View Source
- Chrome HSTS Preload Submission GuideGoogle Chrome Security Team (official)View Source
- Mozilla Observatory: Security Header Configuration GuidelinesMozilla (official)View Source
Related Guides
Continue exploring related technical architecture and defensive guides
TLS · SSL
Modern TLS/SSL Configuration for Web Applications
Master enterprise TLS hardening: TLS 1.3 vs 1.2 differences, Perfect Forward Secrecy ciphers, OCSP stapling, CAA DNS records, and automated Certbot renewal.
XSS · web security
Cross-Site Scripting (XSS): Stored, Reflected & DOM-Based
Exhaustive guide to Cross-Site Scripting: DOM sources and sinks, context-aware output encoding, framework security, and Content Security Policy (CSP Level 3).
HTTPS · SSL
Why HTTPS Matters: Security, SEO & User Trust
Technical guide to HTTPS: cryptographic foundations of TLS 1.3, packet sniffing prevention, HTTP/2 multiplexing performance, and automated Let's Encrypt deployment.
