Table of Contents
Security headers provide defense-in-depth against common web vulnerabilities. This guide covers the essential headers every production application should implement in 2026.
Content Security Policy
CSP prevents XSS attacks by controlling which resources can be loaded.
Basic Implementation
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' https://cdn.example.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
Migration Strategy
- Start with report-only mode:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-violation-report - Collect violation reports
- Fix legitimate violations
- Switch to enforcement mode
- Remove unsafe directives incrementally
HTTP Strict Transport Security
HSTS forces browsers to use HTTPS, preventing downgrade attacks.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Parameters explained:
max-age=31536000: Remember for 1 yearincludeSubDomains: Apply to all subdomainspreload: Include in browser preload lists
Warning
Test thoroughly before enabling includeSubDomains. Any subdomain without HTTPS will become inaccessible.
Permissions Policy
Control which browser features can be used:
Permissions-Policy:
geolocation=(),
microphone=(),
camera=(),
payment=(self),
usb=(),
magnetometer=(),
gyroscope=()
Deny by default, explicitly allow what you need.
Other Critical Headers
X-Content-Type-Options
Prevent MIME type sniffing:
X-Content-Type-Options: nosniff
X-Frame-Options
Prevent clickjacking:
X-Frame-Options: DENY
Referrer-Policy
Control referrer information:
Referrer-Policy: strict-origin-when-cross-origin
Complete Nginx Configuration
add_header Content-Security-Policy "default-src 'self'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
Testing Your Headers
Use these tools to validate your configuration:
- securityheaders.com: Comprehensive header analysis
- Mozilla Observatory: Detailed security scoring
- Browser DevTools: Check headers in Network tab
Automated Testing
const response = await fetch('https://example.com');
const csp = response.headers.get('content-security-policy');
if (!csp || !csp.includes("default-src 'self'")) {
throw new Error('CSP header missing or misconfigured');
}
Summary
Security headers are a critical defense layer. Start with CSP in report-only mode, implement HSTS carefully, deny permissions by default, and test thoroughly. These headers won't prevent all attacks, but they significantly raise the bar for attackers.