Strict-Transport-Security (HSTS)
Discover how HSTS forces secure HTTPS connections and protects against protocol downgrade attacks.
HTTP Strict Transport Security (HSTS) is a crucial web security policy mechanism that forces browsers to use secure HTTPS connections when communicating with your server. This guide explains how HSTS works, why it's essential for your website's security, and how to implement it correctly.
Understanding HSTS#
HTTP Strict Transport Security (HSTS) is a web security mechanism that tells browsers to only communicate with your server over HTTPS. Once a browser receives an HSTS header, it will automatically convert all HTTP requests to HTTPS for the specified duration, even if the user types http:// in the address bar or clicks an HTTP link. This happens entirely in the browser before any network request is made.
- Browsers perform an internal 307 redirect from HTTP to HTTPS before any network traffic
- Protection persists for the duration specified by the max-age directive
- Can extend to all subdomains with the includeSubDomains directive
- Preload lists provide protection from the very first visit to your site
When a browser first visits your HTTPS site and receives the HSTS header, it stores this policy. For all subsequent visits within the max-age window, the browser automatically upgrades HTTP to HTTPS internally. No plaintext HTTP request ever leaves the browser.
The Security Problem HSTS Solves#
Without HSTS, even websites that redirect HTTP to HTTPS have a critical vulnerability window. The initial HTTP request travels across the network in plaintext before the server can respond with a redirect. Attackers positioned on the network (such as on public WiFi) can intercept this first request using a technique called SSL stripping.
- SSL stripping attacks intercept the initial HTTP request and prevent the HTTPS redirect
- Public WiFi networks are common attack vectors for protocol downgrade attacks
- Without HSTS, cookies set without the Secure flag can be stolen over HTTP
- DNS spoofing combined with SSL stripping can completely compromise sessions
Tools like sslstrip make protocol downgrade attacks trivial to execute. An attacker on the same WiFi network can intercept your users' initial HTTP requests and maintain an insecure connection while proxying to your HTTPS server. The user sees no security warnings because they never reach HTTPS.
HSTS Preloading#
The HSTS preload list is maintained by browser vendors and contains domains that should always use HTTPS. When your domain is on the preload list, browsers enforce HTTPS from the very first visit, eliminating even the first-visit vulnerability. Submission requires meeting specific criteria.
- Your site must serve a valid HTTPS certificate on the root domain
- All HTTP traffic must redirect to HTTPS (no content served over HTTP)
- The HSTS header must include max-age of at least 31536000 (one year)
- The header must include both includeSubDomains and preload directives
- All subdomains must also be served over HTTPS
Once your domain is on the preload list, removing it can take months. Make absolutely sure all your subdomains support HTTPS before submitting. Any subdomain that does not support HTTPS will become inaccessible to users.
Implementation Guide#
Deploy HSTS gradually by starting with a short max-age and increasing it once you have verified everything works correctly. This approach minimizes the risk of locking users out of your site if something goes wrong with your HTTPS configuration.
# Apache (.htaccess)
Header always set Strict-Transport-Security \
"max-age=63072000; includeSubDomains; preload"
# Nginx
add_header Strict-Transport-Security \
"max-age=63072000; includeSubDomains; preload" always;
# Node.js / Express
app.use((req, res, next) => {
res.setHeader('Strict-Transport-Security',
'max-age=63072000; includeSubDomains; preload');
next();
});
# Recommended rollout steps:
# 1. Start: max-age=300 (5 minutes)
# 2. Test: max-age=86400 (1 day)
# 3. Grow: max-age=2592000 (30 days)
# 4. Final: max-age=63072000 (2 years)Testing and Verification#
Before enabling HSTS with a long max-age, thoroughly test your HTTPS setup to avoid locking users out. Here are the key verification steps.
- Verify your SSL/TLS certificate is valid and covers all subdomains if using includeSubDomains
- Check that all HTTP URLs properly redirect to HTTPS (including API endpoints)
- Use browser Developer Tools to confirm the HSTS header is present in responses
- Test with curl to verify: curl -I https://yoursite.com | grep Strict-Transport
- Check your eligibility for preloading at hstspreload.org before submitting
# Verify HSTS header
curl -sI https://yoursite.com | grep -i strict-transport
# Expected: Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
# Test that HTTP redirects to HTTPS
curl -sI http://yoursite.com | grep -i location
# Expected: Location: https://yoursite.com/Best Practices and Common Mistakes#
HSTS is highly effective but requires careful implementation. Follow these best practices to avoid common pitfalls that could impact your users.
- Only serve the HSTS header over HTTPS, never over HTTP responses
- Start with a short max-age (5 minutes) and gradually increase to 2 years
- Ensure all subdomains support HTTPS before adding includeSubDomains
- Never set HSTS on localhost or development environments
- Have a plan for certificate renewal to avoid downtime on HSTS-protected domains
- Consider the impact on any services using HTTP-only subdomains before enabling
If your TLS certificate expires while HSTS is active, users will be completely locked out of your site with no way to bypass the browser's security warning. Set up automated certificate renewal and monitoring before enabling long max-age values.
Implementation Examples#
Basic HSTS
Strict-Transport-Security: max-age=31536000Enforces HTTPS for one year (31,536,000 seconds)
Explanation: This basic implementation tells browsers to use HTTPS for all requests to your domain for the next year.
HSTS with Subdomains
Strict-Transport-Security: max-age=31536000; includeSubDomainsApplies HSTS policy to all subdomains as well
Explanation: The includeSubDomains directive extends the HSTS policy to all subdomains of your site.
HSTS with Preload
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadMakes the domain eligible for browser preload lists
Explanation: The preload directive allows your domain to be included in browser preload lists for maximum security.
Key Directives#
max-age
Time in seconds to enforce HTTPS (minimum 1 year recommended)
max-age=31536000includeSubDomains
Apply policy to all subdomains
includeSubDomainspreload
Allow inclusion in browser preload lists
preloadReferences#
Test Your Strict-Transport-Security (HSTS) Configuration
Scan your site to check if Strict-Transport-Security (HSTS) is properly configured.