What is HSTS?
HSTS (HTTP Strict Transport Security) is a web security mechanism that tells browsers to only interact with a website over HTTPS, never HTTP. Once a browser sees an HSTS header, it will automatically upgrade all future requests to HTTPS and refuse to connect over plain HTTP, even if the user explicitly types http://.
Why HSTS Matters
Even with a valid SSL certificate, vulnerabilities exist:
SSL Stripping Attack
1. User types "example.com" (no https://)
2. Attacker intercepts the initial HTTP request
3. Attacker proxies to HTTPS, presents HTTP to user
4. User thinks they're secure, but attacker sees everything
HSTS prevents this by ensuring browsers never make that initial HTTP request.
Benefits of HSTS
- Prevents downgrade attacks: No HTTP fallback possible
- Protects user bookmarks: Even old HTTP bookmarks become HTTPS
- Eliminates mixed content: Subresources also forced to HTTPS
- Improves performance: No HTTP→HTTPS redirects needed
HSTS Header Syntax
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Directives
| Directive | Description |
|---|---|
| max-age | Seconds to remember HSTS (31536000 = 1 year) |
| includeSubDomains | Apply HSTS to all subdomains |
| preload | Consent to browser preload list inclusion |
Implementing HSTS
Nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
Apache
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Cloudflare
Enable in SSL/TLS → Edge Certificates → HTTP Strict Transport Security
Express.js
const helmet = require('helmet');
app.use(helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
preload: true
}));
HSTS Preload List
The HSTS preload list is a list of domains hardcoded into browsers that should only ever be accessed over HTTPS. This eliminates even the first HTTP request vulnerability.
Preload Requirements
1. Valid SSL certificate
2. Redirect all HTTP to HTTPS
3. HSTS header with:
- max-age at least 31536000 (1 year)
- includeSubDomains directive
- preload directive
4. All subdomains must support HTTPS
Submitting to Preload List
1. Verify requirements: Use hstspreload.org to check
2. Submit domain: Enter domain at hstspreload.org
3. Wait for inclusion: Takes weeks to months for browser updates
Preload Warnings
Preload is permanent (practically). Removing from the list takes months and requires browser updates. Only preload if you're certain all subdomains will support HTTPS indefinitely.Checking HSTS
Browser DevTools:1. Open DevTools → Network tab
2. Load the site
3. Check Response Headers for Strict-Transport-Security
Using curl:curl -I https://example.com | grep -i strict
Using DomScan:
curl "https://domscan.net/v1/health?domain=example.com"
# Reports hasHSTS in security details
Preload Status:
Check hstspreload.org to see if a domain is preloaded.
HSTS Deployment Strategy
Phase 1: Short max-age
Start with a short max-age to test:
Strict-Transport-Security: max-age=300
If something breaks, users only cached for 5 minutes.
Phase 2: Increase Duration
After confirming HTTPS works everywhere:
Strict-Transport-Security: max-age=86400
Phase 3: Add Subdomains
Once all subdomains support HTTPS:
Strict-Transport-Security: max-age=2592000; includeSubDomains
Phase 4: Full Deployment + Preload
After months of stable operation:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Then submit to preload list.
Common HSTS Issues
Subdomain without HTTPS: includeSubDomains breaks that subdomain Development environments: HSTS cached from production breaks local dev CDN/Proxy headers: Ensure HSTS header isn't stripped by intermediaries Mixed content: All resources must be HTTPS; HSTS doesn't fix embedded HTTP resourcesHSTS is essential for any website handling sensitive data and strongly recommended for all HTTPS sites.