HTTP security headers are often overlooked, but they provide a simple and effective defense against many common attacks. Correctly configuring 6 headers eliminates entire classes of vulnerabilities.
Why Security Headers Are Critical
A misconfigured (or missing) header can allow:
- Clickjacking (missing X-Frame-Options)
- Malicious script injection via XSS (missing CSP)
- Communication interception in plaintext (missing HSTS)
- Technical stack information leakage (exposed Server header)
WarDek automatically analyzes these 12 headers during every scan.
The 6 Essential Headers
1. Strict-Transport-Security (HSTS)
Forces browsers to use HTTPS for all future connections, even if the user types http://.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Parameters:
max-age=31536000: 1 year (recommended minimum)includeSubDomains: applies the rule to subdomainspreload: enrollment in browser HSTS preload lists
Warning: Once enabled with preload, it's difficult to undo. Test first with a shorter max-age.
2. Content-Security-Policy (CSP)
The most powerful header — and the most complex. Defines allowed sources for each resource type.
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none'
Basic rules:
- Start with
default-src 'self'to block everything by default - Avoid
'unsafe-inline'and'unsafe-eval'as much as possible - Use nonces for legitimate inline scripts
- Enable
Content-Security-Policy-Report-Onlyfirst to test without blocking
3. X-Frame-Options
Protects against clickjacking by controlling who can embed your page in an iframe.
X-Frame-Options: DENY
Or to allow only your own domain:
X-Frame-Options: SAMEORIGIN
Note: frame-ancestors in CSP is more flexible and supersedes X-Frame-Options in modern browsers. Keep both for compatibility.
4. X-Content-Type-Options
Prevents the browser from guessing a resource's MIME type (MIME sniffing), which can lead to malicious code execution.
X-Content-Type-Options: nosniff
Simple, one possible value. Enable it consistently.
5. Referrer-Policy
Controls information sent in the Referer header when navigating between pages.
Referrer-Policy: strict-origin-when-cross-origin
This limits the leakage of internal URLs (which might contain tokens or sensitive data) during cross-origin requests.
6. Permissions-Policy (formerly Feature-Policy)
Controls access to browser APIs (camera, microphone, geolocation, etc.).
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
If your application doesn't use these APIs, disable them to reduce the attack surface.
Headers to Remove
Equally important: remove headers that reveal information about your infrastructure.
Server: Apache/2.4.51→ remove or replace withServer:X-Powered-By: PHP/8.1.0→ remove withexpose_php = OffX-AspNet-Version→ remove in web.config
These headers facilitate automated reconnaissance. An attacker who identifies your Apache or PHP version can immediately look up corresponding CVEs in public vulnerability databases.
Implementation by Stack
Nginx
server {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" 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 "camera=(), microphone=(), geolocation=()" always;
# Remove informational headers
server_tokens off;
proxy_hide_header X-Powered-By;
}
Apache
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"
# Hide version info
ServerTokens Prod
ServerSignature Off
Next.js / Vercel
// next.config.ts
const securityHeaders = [
{ key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains; preload' },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
];
Common Mistakes
Overly permissive CSP. A Content-Security-Policy: default-src * protects against nothing. Start restrictive ('self') and add exceptions one at a time.
HSTS without prior testing. Enabling preload on a domain that is not fully HTTPS can make your site inaccessible. Test with a short max-age (300 seconds) first.
Forgetting subdomains. Without includeSubDomains in HSTS, an attacker can exploit an unsecured subdomain to intercept cookies from the main domain.
Contradictory CSP and X-Frame-Options. If your CSP says frame-ancestors 'self' but X-Frame-Options says DENY, behavior depends on the browser. Align both headers.
How to Check Your Configuration
- WarDek: Automatic scan of all your headers with scores and recommendations
- securityheaders.com: Free tool for a quick check
- curl:
curl -I https://yoursite.comto see raw headers - Browser DevTools: Network tab, select the main request, inspect Response Headers
A good security headers score also improves your SEO ranking (Google favors well-configured HTTPS sites) and your NIS2 compliance. The NIS2 directive (Article 21) explicitly requires network security measures, of which HTTP headers are an integral part.
Frequently Asked Questions
Do I need all 6 headers on every page? Yes. Security headers should be set globally at the server or reverse proxy level, not per-route. Missing a header on a single endpoint creates a vulnerability window that attackers actively scan for.
Will strict CSP break my website? It can, which is why you should deploy in report-only mode first. Use Content-Security-Policy-Report-Only with a reporting endpoint to collect violations for at least one week before switching to enforcement mode.
How do security headers interact with CDNs? Most CDNs (Cloudflare, AWS CloudFront, Fastly) let you add or override response headers at the edge. Configure your security headers at the CDN level to ensure they are applied consistently, even if your origin server configuration varies across deployments.