Fixes
Web Application Security · Updated 2026-05-02
Strict-Transport-Security (HSTS)
Forces browsers to use HTTPS for your domain. Pass needs the header with max-age. Best practice: 2-year max-age + preload.
HTTP Strict Transport Security (HSTS, RFC 6797) tells browsers to use HTTPS for your domain for a specific duration, refusing to even attempt HTTP. Once a browser receives a valid HSTS header from your site, it rewrites every http:// request to https:// for the lifetime of the policy, even if the user clicks an http link. This closes off SSL-stripping attacks, accidental HTTP requests, and the brief window where a man-in-the-middle could intercept the first HTTPS upgrade.
Important: HSTS is honored only when the header arrives over HTTPS. Browsers ignore HSTS headers received over HTTP. Make sure every primary host already serves HTTPS (see HTTPS Consistency) before relying on HSTS.
How the check works
Per primary host, the check looks at the Strict-Transport-Security response header. If the header value contains max-age= (any value), the host gets full credit for this sub-weight (15 pts). If the header is missing or has no max-age=, zero.
What this check does NOT validate today: the actual max-age value, the includeSubDomains directive, or the preload directive. A host with max-age=1 passes the same as max-age=63072000. The recommended values below are best practice, not what the score requires; the score only checks for header presence with a max-age.
How the verdict maps to evidence
- Pass (15/15 per host): Strict-Transport-Security header present with max-age=.
- Fail (0/15 per host): header missing or missing max-age=.
Fix: add the header
The minimum to score: send the header on every HTTPS response. The recommended value (best practice, not just for scoring):
Recommended HSTS header (production)
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload- max-age=63072000: two years in seconds. The HSTS Preload List requires at least one year (31536000); two years is the modern recommendation.
- includeSubDomains: applies HSTS to every subdomain of yourdomain.tld. High blast radius (see Common pitfalls).
- preload: opts you into the HSTS Preload List, which ships HSTS for your domain in browser-default lists so users are protected even before their first visit.
Phased rollout
Do not jump to two years immediately. Once HSTS is set, browsers cannot un-cache the policy until max-age expires; if HTTPS breaks during that window, your users cannot reach you. Phase in:
- Week 1: max-age=300 (5 minutes). Lets you back out fast if anything breaks.
- Week 2-3: max-age=86400 (1 day). Confirms HSTS works without long-term commitment.
- Week 4: max-age=604800 (1 week). Real-world testing.
- Once stable: max-age=63072000 (2 years), add includeSubDomains if every subdomain serves HTTPS, then add preload and submit at hstspreload.org.
Per-server snippets
nginx
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;Apache
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"Caddy
header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"Cloudflare (dashboard path)
SSL/TLS → Edge Certificates → HTTP Strict Transport Security (HSTS)
Enable, set Max-Age to 12 months minimum, plus includeSubDomains and Preload as appropriate.AWS CloudFront (response headers policy)
In a Response Headers Policy, add:
Header: Strict-Transport-Security
Value: max-age=63072000; includeSubDomains; preloadHSTS Preload List
The HSTS Preload List is a list of domains baked into Chrome, Firefox, Safari, and Edge that always use HTTPS, even on first visit. Submission requirements at hstspreload.org:
- Serve a valid HTTPS cert.
- Redirect HTTP to HTTPS on the apex.
- All subdomains (including www) serve HTTPS.
- HSTS header on the apex with max-age at least 31536000 (1 year), includeSubDomains, and preload.
Once submitted, removal takes weeks to months because the list is shipped in browser releases. Only preload after running with includeSubDomains for several weeks without issues.
Verify the fix
- curl -sI https://yourdomain.tld | grep -i strict-transport-security should show the header.
- Test with hstspreload.org's checker before submitting; it validates all preload requirements.
- Check the browser's HSTS state: in Chrome, visit chrome://net-internals/#hsts and query yourdomain.tld. In Firefox, about:preferences#privacy lets you clear per-site data and see HSTS state.
- Re-run the RedScore lookup. Pass requires the header on every primary HTTPS host.
Common pitfalls
- HSTS over HTTP is ignored. Browsers only honor HSTS headers received over HTTPS. Sending the header on http:// responses does nothing. Make sure HTTPS works before relying on HSTS.
- includeSubDomains breaks subdomains that serve HTTP. The directive applies HSTS to every *.yourdomain.tld. If admin.yourdomain.tld or some legacy subdomain still serves HTTP only, browsers stop loading it. Audit every subdomain before turning includeSubDomains on.
- Preload commitment is hard to undo. Once preloaded, removal requests take weeks and propagate over the next browser release cycle. If you might rebrand or move domains soon, hold off on preload.
- Rolling back HSTS. Browsers honor the header for max-age regardless of what the current header says. To shorten, set max-age=0 in the response and wait for cached entries to expire. There is no instant unset.
- Header at one layer overridden at another. CDN, load balancer, and origin can all set the header. The closest-to-client value wins; if your CDN sets max-age=0 and origin sets max-age=63072000, browsers see max-age=0. Set the header at one layer and confirm with curl.
- HSTS on www but not apex (or vice versa). Each hostname has its own HSTS state in the browser. If only www has HSTS, an apex visit still risks SSL strip on first contact. Set HSTS on every hostname you serve.
What to do next
See how these recommendations apply to your site's current scan results.
Scan domain