HTTP Security 15 min readLast updated September 2, 2026

Security Headers Guide — CSP, HSTS, X-Frame-Options

This security headers guide covers CSP, HSTS, X-Frame-Options, Permissions-Policy, and related HTTP controls — what each header blocks, why it matters, and copy-paste configs for Nginx, Apache, and Express. Vulnify's free headers analyzer checks those same headers on a live URL: CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy. No signup for Quick Check.

Content-Security-Policy (CSP)

CSP is the most powerful security header, preventing XSS attacks by controlling which resources can be loaded. It tells browsers which sources are trusted for scripts, styles, images, and other content.

CSP Protects Against

  • Cross-Site Scripting (XSS) attacks
  • Data injection attacks
  • Clickjacking (with frame-ancestors)
  • Packet sniffing (with upgrade-insecure-requests)

Basic CSP Example

HTTP Header
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.yourdomain.com

CSP Directives Explained

DirectiveControlsExample
default-srcFallback for all resources'self'
script-srcJavaScript sources'self' https://cdn.example.com
style-srcCSS sources'self' 'unsafe-inline'
img-srcImage sources'self' data: https:
connect-srcAPI/fetch destinations'self' https://api.example.com
frame-ancestorsWho can embed this page'none'

Strict-Transport-Security (HSTS)

HSTS forces browsers to use HTTPS only, which blocks protocol-downgrade attacks and cookie theft on the wire. Enable it after the certificate chain is valid — then confirm with the HSTS checker and this security headers guide.

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

HSTS Checklist

  • Set max-age to at least 1 year (31536000 seconds)
  • Include includeSubDomains if all subdomains use HTTPS
  • Add preload and submit to hstspreload.org
  • Ensure HTTPS works correctly before enabling

X-Frame-Options

X-Frame-Options stops other sites from embedding your pages in an iframe, which is the classic clickjacking setup. Prefer DENY unless a same-origin widget needs SAMEORIGIN. CSP frame-ancestors is the modern complement — test both with the free headers analyzer after you deploy.

Options
# Prevent all framing
X-Frame-Options: DENY

# Allow framing from same origin only
X-Frame-Options: SAMEORIGIN

X-Content-Type-Options

Prevents browsers from MIME-sniffing, which can lead to XSS attacks.

Always Use
X-Content-Type-Options: nosniff

Referrer-Policy

Controls how much referrer information is sent with requests.

Recommended
# Good balance of privacy and functionality
Referrer-Policy: strict-origin-when-cross-origin

# Maximum privacy
Referrer-Policy: no-referrer

Permissions-Policy

Controls which browser features can be used (formerly Feature-Policy).

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

Complete Configurations

Nginx

Nginx - /etc/nginx/conf.d/security-headers.conf
# Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

Apache

Apache - .htaccess or httpd.conf
<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set Content-Security-Policy "default-src 'self';"
    Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>

Express.js (Node.js)

Express with Helmet
const helmet = require('helmet');

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'unsafe-inline'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
    },
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
  },
  frameguard: { action: 'sameorigin' },
  referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
}));

Security Headers FAQ

A security headers guide for CSP, HSTS, and X-Frame-Options explains those HTTP response headers — what each blocks, how to configure them on Nginx, Apache, or Express, and how to verify with a free online headers analyzer.

Check Your Security Headers Now

Use our free analyzer to see which headers you're missing and get copy-paste fixes.

Analyze Your Headers