Skip to main content

How to Configure Secure Headers and a Content Security Policy

Add HSTS, nosniff, referrer, and framing protections, then author a Content Security Policy and roll it out safely with report-only mode before enforcing it to mitigate XSS.

Difficulty
Intermediate
Duration
40 minutes
Steps
5

What and why

HTTP security headers instruct the browser to enforce protections the server cannot. The most important is a Content Security Policy (CSP), which restricts where scripts, styles, and other resources may load from, sharply reducing the impact of cross-site scripting (XSS). Other headers harden transport and framing.

Prerequisites

  • A web app served over HTTPS.
  • Browser developer tools to read console errors.
  • Basic understanding of HTTP headers.

Steps

1. Enable HSTS

HTTP Strict Transport Security forces HTTPS:

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

Only set this once HTTPS is solid, because browsers will refuse plain HTTP for the max-age duration.

2. Set framing and content-type protections

X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin

Prefer the CSP frame-ancestors directive over the legacy X-Frame-Options header to control framing.

3. Draft a Content Security Policy

Start restrictive and allow only what you need:

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; frame-ancestors 'none'; base-uri 'self'

For inline scripts you cannot remove, use a per-request nonce (script-src 'self' 'nonce-<random>') rather than unsafe-inline.

4. Roll out CSP in report-only mode

Deploy with the report-only header first so violations are logged but nothing breaks:

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

Collect reports, find legitimate resources the policy blocks, and add them.

5. Enforce and tighten the policy

Once reports are clean, switch to the enforcing Content-Security-Policy header. In Express, the helmet middleware sets these headers with sensible defaults:

const helmet = require('helmet');
app.use(helmet());

In Nginx, use add_header directives in the server block.

Verification

  • Response headers include HSTS, nosniff, and a CSP.
  • The browser console shows no unexpected CSP violations.
  • An injected <script> from another origin is blocked.

Next Steps

Add Subresource Integrity for third-party scripts, scan headers with an online analyzer, and review the CSP whenever you add new third-party resources so the policy stays both strict and functional.

Prerequisites

  • A web application served over HTTPS
  • Browser developer tools
  • Basic HTTP header knowledge

Steps

  • 1
    Enable HSTS
  • 2
    Set framing and content-type protections
  • 3
    Draft a Content Security Policy
  • 4
    Roll out CSP in report-only mode
  • 5
    Enforce and tighten the policy

Category

Security