Essential Security Headers Every Web App Needs
Security headers are HTTP response headers that provide an additional layer of protection for your web applications. They help prevent common attacks like cross-site scripting (XSS), clickjacking, and man-in-the-middle attacks. This guide covers the essential security headers every web application should implement.
Why Security Headers Matter
Security headers act as instructions to browsers on how to handle your website's content. They can:
Critical Security Headers
1. Content-Security-Policy (CSP)
CSP helps prevent XSS attacks by controlling which resources the browser is allowed to load.
Basic Implementation:
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';Recommended Configuration:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none';Key Directives:
2. Strict-Transport-Security (HSTS)
HSTS forces browsers to use HTTPS connections, preventing protocol downgrade attacks.
Implementation:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadParameters:
3. X-Frame-Options
Prevents your site from being embedded in frames, protecting against clickjacking.
Options:
X-Frame-Options: DENYor
X-Frame-Options: SAMEORIGINNote: Modern CSP frame-ancestors directive is preferred, but X-Frame-Options provides backward compatibility.
4. X-Content-Type-Options
Prevents browsers from MIME-sniffing, forcing them to respect declared content types.
Implementation:
X-Content-Type-Options: nosniffThis prevents browsers from interpreting files as different MIME types, reducing the risk of XSS attacks.
5. Referrer-Policy
Controls how much referrer information is sent with requests.
Options:
Referrer-Policy: strict-origin-when-cross-originCommon Values:
6. Permissions-Policy (formerly Feature-Policy)
Controls which browser features and APIs can be used.
Example:
Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=(self)Common Features:
7. X-XSS-Protection
Legacy header for older browsers. Modern browsers have built-in XSS protection.
Implementation:
X-XSS-Protection: 1; mode=blockNote: This is less important with proper CSP implementation.
Implementation Examples
Nginx Configuration
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'" always;
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 "geolocation=(), microphone=(), camera=(), payment=(self)" always;Apache Configuration
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(self)"Express.js (Node.js)
const helmet = require('helmet');
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
fontSrc: ["'self'", "data:"],
connectSrc: ["'self'"],
frameAncestors: ["'none'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
},
frameguard: { action: 'deny' },
noSniff: true,
referrerPolicy: { policy: 'strict-origin-when-cross-origin' }
}));Testing Your Security Headers
Use these tools to verify your headers:
Common Mistakes
1. Too Restrictive CSP: Can break legitimate functionality
2. Missing includeSubDomains: HSTS should cover all subdomains
3. Incorrect CSP Syntax: Can cause headers to be ignored
4. Not Testing: Always test headers in staging before production
Conclusion
Security headers are a crucial part of web application security. By implementing these headers correctly, you can significantly reduce your application's attack surface and protect your users from common web vulnerabilities.
Remember to:
Stay secure!