The First-Request Problem
HTTPS encrypts traffic after the 연결 is established, but the initial request to an HTTP URL is still sent in cleartext. An attacker on the same 네트워크 can intercept that first request, perform an SSL stripping attack, and downgrade the user to HTTP for the entire session.
HTTP Strict Transport Security (HSTS) closes this window. Once a browser receives an HSTS header, it automatically upgrades all future HTTP requests to HTTPS and refuses to connect if the certificate is invalid.
How HSTS Works
The 서버 sends the Strict-Transport-Security header in the HTTPS response:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
| Directive | Description |
|---|---|
max-age=<seconds> | How long the browser should remember to use HTTPS only |
includeSubDomains | Apply the policy to all subdomains |
preload | Signal inclusion in browser preload lists |
Once processed, the browser:
- Rewrites all
http://links tohttps://for the domain - Refuses to connect if TLS handshake fails or certificate is invalid
- Caches the policy for the duration of
max-age
Configuring HSTS on Servers
NGINX
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/example.pem;
ssl_certificate_key /etc/ssl/private/example.key;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
}
The always parameter ensures the header is sent even on error pages.
Apache
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Cloudflare
Cloudflare enables HSTS through the dashboard: SSL/TLS > Edge Certificates > HTTP Strict Transport Security. You can toggle preload and includeSubDomains with one click. Cloudflare also offers a “No Sniff” mode that prevents downgrade attacks at the edge.
Express/Node.js
const helmet = require("helmet");
app.use(helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
preload: true
}));
The HSTS Preload List
The max-age directive only works after the user has visited your site once. The HSTS preload list baked into Chrome, Firefox, Safari, and Edge hard-codes domains that should always use HTTPS, eliminating the first-request vulnerability entirely.
To submit your domain:
- Ensure your site returns a valid HSTS header with
preload - Go to hstspreload.org
- Submit your domain
Requirements for preload inclusion:
| Requirement | Detail |
|---|---|
| Valid certificate | TLS on all subdomains |
max-age | At least 31536000 (1 year) |
includeSubDomains | Required |
preload | Present in header |
| Redirects | HTTP → HTTPS for all requests |
Warning: Preload inclusion is permanent for the domain. You cannot easily remove your domain from the list once accepted.
Testing HSTS 배포
Several tools verify your HSTS configuration:
# curl with headers
curl -sI https://example.com | grep -i strict-transport
# Security Headers
# https://securityheaders.com
# SSL Labs
# https://www.ssllabs.com/ssltest/analyze.html?d=example.com
# Using the HSTS check script
curl -s https://hstspreload.org/api/v2/check?domain=example.com
Common Pitfalls
| Issue | Consequence | Fix |
|---|---|---|
max-age too short | Policy expires frequently | Set to at least 1 year |
Missing includeSubDomains | Subdomains unprotected | Add the directive |
| HTTP-only site serves HSTS | Header ignored | Serve only over HTTPS |
| Mixed content | Browser blocks insecure resources | Audit all http:// references |
| Preload without preparation | Permanent HTTPS requirement | Test with max-age=0 first |
Clearing HSTS During Development
To clear a cached HSTS policy in the browser:
- Chrome:
chrome://net-internals/#hsts→ Delete domain - Firefox: Clear browsing history for the domain
- Safari: Clear website data in Preferences
As a developer, use max-age=0 to signal policy revocation:
Strict-Transport-Security: max-age=0
Summary
HSTS is a fundamental security header that ensures HTTPS is always used after the first visit, preventing SSL stripping and downgrade attacks. Configure it with max-age=31536000, includeSubDomains, and optionally preload for full protection. Always test your configuration with security checkers and clear the HSTS cache during development to avoid lockouts.

