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
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.comCSP Directives Explained
| Directive | Controls | Example |
|---|---|---|
default-src | Fallback for all resources | 'self' |
script-src | JavaScript sources | 'self' https://cdn.example.com |
style-src | CSS sources | 'self' 'unsafe-inline' |
img-src | Image sources | 'self' data: https: |
connect-src | API/fetch destinations | 'self' https://api.example.com |
frame-ancestors | Who 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.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadHSTS Checklist
- Set max-age to at least 1 year (31536000 seconds)
- Include
includeSubDomainsif all subdomains use HTTPS - Add
preloadand 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.
# Prevent all framing
X-Frame-Options: DENY
# Allow framing from same origin only
X-Frame-Options: SAMEORIGINX-Content-Type-Options
Prevents browsers from MIME-sniffing, which can lead to XSS attacks.
X-Content-Type-Options: nosniffReferrer-Policy
Controls how much referrer information is sent with requests.
# Good balance of privacy and functionality
Referrer-Policy: strict-origin-when-cross-origin
# Maximum privacy
Referrer-Policy: no-referrerPermissions-Policy
Controls which browser features can be used (formerly Feature-Policy).
Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=()Complete Configurations
Nginx
# 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
<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)
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.