Back to Blog
Web SecurityHeadersGuide

Security Headers: The Complete Implementation Guide

January 15, 20264 min readRedVolt Team

Security headers are the lowest-effort, highest-impact security improvement you can make to a web application. They're response headers that instruct the browser to enable built-in security features — and they take minutes to implement.

Yet in our audits, over 70% of applications are missing at least three critical security headers.

The Essential Headers

73%

Missing CSP

61%

Missing HSTS

44%

Missing X-Frame-Options

38%

Missing Permissions-Policy

Content-Security-Policy (CSP)

critical

The most powerful security header. CSP tells the browser which sources of content are trusted, effectively neutralizing most XSS attacks.

Without CSP

  • Injected script tags execute immediately
  • Inline event handlers (onclick, onerror) run attacker code
  • Data exfiltration via img src to attacker server
  • Malicious iframes load phishing pages

With CSP

  • Only scripts from whitelisted domains execute
  • Inline scripts blocked unless nonce-based
  • Connections restricted to known origins
  • Frame sources explicitly controlled

💡Start with Report-Only

Deploy CSP in report-only mode first (Content-Security-Policy-Report-Only) to identify violations without breaking your application. Fix violations, then switch to enforcement.

Strict-Transport-Security (HSTS)

high

Forces browsers to only connect via HTTPS, preventing SSL stripping attacks.

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

  • max-age=31536000 — Remember for 1 year
  • includeSubDomains — Apply to all subdomains
  • preload — Submit to browser preload lists so even the first visit is HTTPS

⚠️HSTS Preload Is Permanent

Once you submit to the HSTS preload list and browsers ship the update, there is no quick way to undo it. Make sure all your subdomains support HTTPS before adding includeSubDomains and preload.

X-Frame-Options / frame-ancestors

medium

Prevents your site from being embedded in iframes on other domains — the primary defense against clickjacking.

  • X-Frame-Options: DENY — Never allow framing
  • X-Frame-Options: SAMEORIGIN — Only allow framing by your own domain
  • Modern alternative: Content-Security-Policy: frame-ancestors 'self'

Permissions-Policy

Controls which browser features your site can use — camera, microphone, geolocation, payment API, etc.

Recommended: Disable everything you don't need:

Permissions-Policy Strategy

Deny by default

Start with a restrictive policy that disables all features: camera=(), microphone=(), geolocation=(), payment=()

Enable only what you use

If your app needs geolocation: geolocation=(self). If you embed a payment iframe: payment=(self "https://payments.example.com")

Prevent feature abuse

Even if an attacker achieves XSS, they can't access the camera, microphone, or other sensitive APIs if the permissions policy blocks them.

Other Important Headers

Additional Security Headers

X-Content-Type-Options: nosniff

Prevents browsers from MIME-sniffing a response away from the declared Content-Type. Stops attacks where an attacker uploads a .jpg that's actually JavaScript.

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

Controls how much referrer information is sent with requests. Prevents leaking sensitive URL parameters to third parties.

Cross-Origin-Opener-Policy: same-origin

Isolates your browsing context from cross-origin windows. Prevents Spectre-style side-channel attacks and cross-window manipulation.

Cross-Origin-Resource-Policy: same-origin

Prevents other origins from reading your resources. Blocks unauthorized cross-origin data access.

Implementation by Platform

Nginx

ℹ️Nginx Configuration

Add headers in your server block: add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always;

Next.js

Use the headers() function in next.config.js to set headers on all routes. For CSP with nonces, use middleware to generate a per-request nonce.

Express.js

Use the helmet middleware — it sets sensible security headers with one line: app.use(helmet()). Customize individual headers as needed.

Cloudflare / CDN

Most CDNs support adding response headers at the edge. This is often the easiest approach for static sites and ensures headers are set even if your application server misconfigures them.

Testing Your Headers

01

Scan

Use securityheaders.com or our AI scanner to check your current headers

02

Implement

Add missing headers in report-only mode first

03

Test

Verify your application still works — CSP is the most likely to break things

04

Enforce

Switch from report-only to enforcement after fixing violations

The Quick Win

Security headers are one of the few areas where you can significantly improve your security posture in under an hour. Start with these five, in order of impact:

  1. Content-Security-Policy — Neutralizes most XSS
  2. Strict-Transport-Security — Forces HTTPS everywhere
  3. X-Content-Type-Options — Prevents MIME confusion
  4. X-Frame-Options — Blocks clickjacking
  5. Permissions-Policy — Restricts browser feature access

Our AI scanner checks all security headers automatically as part of every audit. Run a scan to see exactly which headers your application is missing — and get implementation guidance for each one.

Want to secure your application or smart contract?

Request an Expert Review