Why HTTP security headers matter
Modern web browsers come equipped with powerful defensive mechanisms designed to protect visitors against Cross-Site Scripting (XSS), clickjacking, MIME-type sniffing, and man-in-the-middle packet injection.
However, browsers operate in standard compatibility mode by default. They will not activate these protective barriers unless your web server explicitly instructs them to do so via HTTP response headers.
Adding security headers requires no changes to your application code or database. A few simple lines in your Nginx, Apache, Caddy, or Next.js configuration can eliminate entire categories of critical OWASP vulnerabilities.
The 6 essential security headers
1. Strict-Transport-Security (HSTS)
HSTS guarantees that client browsers connect to your website exclusively over encrypted HTTPS, completely ignoring accidental http:// links.
- Recommended Value:
max-age=31536000; includeSubDomains; preload - What it does: Enforces a 1-year (
31,536,000seconds) TLS upgrade, protects all subdomains, and qualifies your domain for the global browser HSTS preload list.
2. Content-Security-Policy (CSP)
Widely recognized as the ultimate client-side defense against Cross-Site Scripting (XSS), CSP restricts the exact origins from which scripts, styles, fonts, and images can execute.
- Recommended Baseline:
default-src 'self'; script-src 'self'; object-src 'none'; img-src 'self' data: https:; - What it does: Prevents malicious injected
<script>tags from executing and sending stolen cookies or auth tokens to rogue endpoints.
3. X-Frame-Options
Protects your visitors against clickjacking (UI redress attacks) by forbidding third-party sites from embedding your web pages inside invisible <iframe> overlays.
- Recommended Value:
SAMEORIGIN(orDENY) - What it does: Disallows external domains from embedding your login forms, checkout pages, or settings panels inside iframes.
4. X-Content-Type-Options
Prevents browsers from MIME-sniffing a response away from the declared Content-Type.
- Recommended Value:
nosniff - What it does: Forces browsers to strictly respect declared file types. If a user uploads an image containing malicious JavaScript,
nosniffprevents the browser from executing that image as script code.
5. Referrer-Policy
Controls what private information (pathnames, user IDs, authentication tokens in URLs) is broadcast in the Referer header when visitors click outbound links.
- Recommended Value:
strict-origin-when-cross-origin - What it does: Sends full path data only to the same origin; for cross-origin HTTPS visits, it only transmits your domain name (e.g.,
https://yourdomain.com/), protecting private query parameters.
6. Permissions-Policy (Formerly Feature-Policy)
Grants granular control over modern browser hardware APIs, disabling sensitive device capabilities unless explicitly authorized.
- Recommended Value:
camera=(), microphone=(), geolocation=() - What it does: Blocks third-party scripts or embedded ads from secretly accessing user webcam hardware, audio microphones, or geolocation coordinates.
Nginx configuration snippet
To enable all six security headers across your entire Nginx web server, add the following directives inside your server { ... } block (typically located in /etc/nginx/sites-available/ or /etc/nginx/conf.d/):
# /etc/nginx/conf.d/security-headers.conf
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none';" always;
# Hide server version details from attackers
server_tokens off;
Test your configuration syntax and reload Nginx:
sudo nginx -t && sudo systemctl reload nginx
Apache (.htaccess) configuration snippet
If you run an Apache web server, ensure mod_headers is enabled (sudo a2enmod headers) and place the following block in your root .htaccess or virtual host configuration:
# .htaccess Security Headers
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none';"
</IfModule>
# Suppress Apache signature & version leaks
ServerSignature Off
ServerTokens Prod
Caddy and Next.js configuration
Caddy Server (Caddyfile)
Caddy automatically handles HTTPS, but adding custom headers is clean and concise:
yourdomain.com {
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
Permissions-Policy "camera=(), microphone=(), geolocation=()"
Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none';"
-Server
}
reverse_proxy localhost:3000
}
Next.js (next.config.js)
In Next.js applications, configure headers directly in next.config.js:
// next.config.js
module.exports = {
poweredByHeader: false, // Disables X-Powered-By: Next.js
async headers() {
return [
{
source: '/(.*)',
headers: [
{ key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains; preload' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
{ key: 'Content-Security-Policy', value: "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none';" },
],
},
];
},
};
How to test your security headers grade
After applying your server changes, verify your headers using our free HTTP Security Headers Validator.
The validator analyzes your live response headers, flags missing defenses or information leaks (like Server or X-Powered-By version broadcasting), and assigns a letter grade from A+ to F.
You can also inspect response headers directly via terminal curl:
curl -I "https://yourdomain.com"
