Intermediate·11 min read·Updated 2026-10-15

Complete Guide to HTTP Security Headers (CSP, HSTS & More)

Original WeSecureX guide for authorized testing of sites you own. Linked Sources are citations for verification - not copied articles. Ads are not served on this page.

Modern web browsers implement powerful security sandboxes, but they require explicit instructions from web servers to enforce them. By configuring HTTP security headers, engineering teams can neutralize entire vulnerability classes - including clickjacking, cross-site scripting, MIME sniffing, and insecure transport downgrades - with minimal latency overhead. This guide details the essential security headers, explains directive syntax, and provides battle-tested configurations for Nginx, Next.js, and Apache.

Complete Guide to HTTP Security Headers (CSP, HSTS & More)
HTTP security headers · WeSecureX Research Lab
Quick Answer

HTTP security headers are response directives sent by web servers to instruct client browsers on how to enforce defense-in-depth security policies. Essential headers include Strict-Transport-Security (enforces HTTPS), Content-Security-Policy (prevents XSS and unauthorized resource loading), X-Frame-Options (prevents clickjacking), X-Content-Type-Options (blocks MIME-sniffing), and Permissions-Policy (restricts browser APIs).

Key Takeaways
  • HTTP security headers provide essential defense-in-depth implemented directly at the browser layer.
  • HSTS enforces HTTPS permanently, protecting against SSL stripping and downgrade attacks.
  • CSP Level 3 restricts resource loading and execution, neutralizing cross-site scripting.
  • X-Frame-Options and `frame-ancestors` eliminate clickjacking vulnerabilities.
  • Always use `always` in Nginx `add_header` to ensure headers are sent on error responses.
Visual Diagram · HTTP Security Header Defense Infrastructure
1

1. Server Issues Security Headers

Origin server attaches CSP, HSTS, and X-Frame-Options response headers to all HTTPS traffic.

2

2. Browser Restricts Resource Fetching

Content Security Policy blocks inline scripts, unauthorized frame embedding, and un-encrypted HTTP requests.

3

3. HSTS Enforces HTTPS Strict Encryption

Browser automatically upgrades all HTTP requests to HTTPS, preventing SSL stripping attacks.

4

4. Automated Security Header Audit

Domain header compliance is monitored continuously on [WeSecureX Security Console](/scanner).

ShareShare on XLinkedIn

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 HeaderRecommended Production DirectiveKey Defensive PurposeObsoleted / Deprecated Alternative
Content-Security-Policy (CSP)default-src 'self'; script-src 'self' 'nonce-...'; object-src 'none';Mitigates XSS, data injection, and clickjackingReplaces X-XSS-Protection
Strict-Transport-Security (HSTS)max-age=63072000; includeSubDomains; preloadEnforces HTTPS; blocks SSL-stripping MITMReplaces insecure HTTP redirects
X-Content-Type-OptionsnosniffPrevents MIME-sniffing attacks on uploadsMandatory for all web assets
X-Frame-OptionsDENY or SAMEORIGINDefends against Clickjacking framing attacksSuperseeded by CSP frame-ancestors
Permissions-Policycamera=(), microphone=(), geolocation=()Disables unnecessary hardware APIsReplaces deprecated Feature-Policy
Referrer-Policystrict-origin-when-cross-originPrevents URL path & token leakage in Referer headerObsoletes default browser leaks
Cross-Origin-Opener-Policy (COOP)same-originIsolates browsing context (Spectre mitigation)Required for SharedArrayBuffer
Cross-Origin-Embedder-Policy (COEP)require-corpEnforces cross-origin resource permissionsWorks with COOP for complete isolation

Every production web application should implement the following seven foundational headers:

  1. Strict-Transport-Security (HSTS): Enforces HTTPS and prevents SSL-stripping MITM attacks.
  2. Content-Security-Policy (CSP): Restricts origins for scripts, styles, images, and child frames.
  3. X-Frame-Options: Prevents clickjacking by restricting iframe embedding.
  4. X-Content-Type-Options: Prevents MIME sniffing by forcing the browser to adhere strictly to declared Content-Type.
  5. Referrer-Policy: Protects visitor privacy by restricting referrer URLs sent to third parties.
  6. Permissions-Policy: Restricts browser hardware features (camera, microphone, geolocation).
  7. 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

http
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • max-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:

http
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': Supersedes X-Frame-Options: DENY in 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:

http
X-Frame-Options: DENY
# Or allow framing only by your own origin:
X-Frame-Options: SAMEORIGIN

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

http
X-Content-Type-Options: nosniff

Permissions-Policy & Referrer-Policy

Permissions-Policy (Formerly Feature-Policy)

Explicitly disables access to sensitive device APIs that your web application does not need:

http
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()

Referrer-Policy

Controls how much URL information is sent in the Referer header when visitors navigate away:

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

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

javascript
// 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:

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

nginx
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 WeSecureX Security Scanner.

Automated Security Header Auditing & CSP Generation with WeSecureX

HTTP response headers represent the first line of defense between your web application and the end-user's browser. However, configuring headers manually often results in syntax errors, obsolete directives (such as X-XSS-Protection), or overly permissive policies that leave sites exposed to clickjacking and data injection.

Comprehensive Header Intelligence via WeSecureX

When you scan a domain with the WeSecureX Free Vulnerability Scanner, our engine performs an instant cryptographic and protocol analysis:

  1. HSTS & Preload Readiness: Validates Strict-Transport-Security max-age (minimum 31536000 seconds), includeSubDomains, and preload flag eligibility for Chromium and Firefox HSTS preloading.
  2. CSP Level 3 Evaluation: Deconstructs your Content-Security-Policy into individual directives, flagging missing default-src, wildcard hosts (*), and dangerous permissions ('unsafe-inline', 'unsafe-eval').
  3. Clickjacking & Framing Verification: Tests for the presence of X-Frame-Options: DENY and CSP frame-ancestors 'none' to prevent framing attacks.
  4. Permissions-Policy Auditing: Verifies that sensitive browser capabilities (camera, microphone, geolocation) are explicitly disabled for unauthorized third-party embeds.

Instant Header Generation

In addition to flagging vulnerabilities in the Vulnerabilities Dashboard, WeSecureX generates copy-paste configuration snippets for Nginx, Cloudflare Workers, Apache, and Next.js, allowing your development team to achieve an A+ Security Grade within minutes. Test your live headers right now with our Free HTTP Security Headers Checker, verify transport with the Free SSL Checker, or consult our Website Security Guide.

bash
# WeSecureX Header Audit Scorecard
$ wesecurex audit --target https://example.com --module headers

[HEADER] Strict-Transport-Security: max-age=63072000; includeSubDomains; preload [PASS]
[HEADER] X-Content-Type-Options: nosniff [PASS]
[HEADER] X-Frame-Options: DENY [PASS]
[HEADER] Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-...' [PASS]
[HEADER] Permissions-Policy: camera=(), microphone=(), geolocation=() [PASS]
[HEADER] Referrer-Policy: strict-origin-when-cross-origin [PASS]
[SCORE] 100/100 (Grade A+) - Ready for Chrome HSTS Preload List

Apply it with WeSecureX

Add a hostname you own or are allowed to test, run a scan, and open the findings for that target. A confirmed result includes the request WeSecureX sent and the response the site returned, so you can reproduce it, fix it in your own application, and rescan the same host to confirm the issue is gone. WeSecureX is automated testing, not a manual penetration test, and a clean report is not a promise that every weakness is gone.

Checks that belong with this topic

  • Enable Strict-Transport-Security with minimum `max-age=31536000` (1 year).
  • Deploy Content-Security-Policy starting in Report-Only mode to audit dependencies.
  • Set `X-Frame-Options: DENY` or `SAMEORIGIN` to prevent clickjacking.
  • Set `X-Content-Type-Options: nosniff` to enforce strict MIME-type handling.
  • Configure `Referrer-Policy: strict-origin-when-cross-origin` to protect URL privacy.
  • Restrict unneeded device APIs via `Permissions-Policy` (camera, microphone, location).

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

WeSecureX 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.

HSTS preloading submits your domain to a browser-hardcoded list enforcing HTTPS. Configure header: Strict-Transport-Security: max-age=63072000; includeSubDomains; preload, then submit to hstspreload.org.

It prevents browsers from MIME-sniffing a response away from the declared Content-Type, mitigating script execution from uploaded user files or text files.

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

Continue exploring related technical architecture and defensive guides

Security Research & Engineering Articles

All articles