Updated 10 hours ago
HTTP Strict Transport Security (HSTS) is a promise your server makes to browsers: from now on, we only communicate over HTTPS. Once a browser accepts this promise, it refuses to even attempt HTTP. No redirect needed. No user decision. The browser simply won't do it.
This single header—Strict-Transport-Security—provides remarkable protection against an entire class of attacks. But it has one haunting weakness.
The Promise
When your server sends an HSTS header over HTTPS, the browser stores this commitment:
This says: "For the next year, only speak to me securely. Apply this to all my subdomains too."
From that moment, if a user types http://example.com or clicks an old HTTP link, the browser doesn't send that request. It internally rewrites it to HTTPS before anything leaves the machine. No HTTP packet ever touches the network.
Even better: if something's wrong with the HTTPS connection—expired certificate, hostname mismatch, anything suspicious—the browser refuses entirely. No "proceed anyway" button. The promise was HTTPS or nothing, and the browser honors it.
The Vulnerability
Here's the terrifying gap: HSTS only works after the first successful HTTPS visit.
Imagine a user at a coffee shop, connecting for the first time to your site. They type example.com. Their browser, having never seen your HSTS policy, tries HTTP first. That single unencrypted request floats across the hostile network.
An attacker sitting on that network intercepts it. They can serve fake content, steal credentials, inject malware—anything. The user has no HSTS protection because they've never received it yet.
This is the first-visit problem. The moment you most need protection is the one moment you don't have it.
How Browsers Remember
When a browser receives an HSTS header, it stores three things:
The domain: Which site made the promise.
The expiration: When the promise expires (controlled by max-age).
The scope: Whether subdomains are included.
This persists across browser restarts, cleared only when the time expires or the site explicitly revokes it with max-age=0.
Every time a user visits and receives the header again, the timer resets. Regular visitors continuously refresh their protection.
The Directives
max-age sets the duration in seconds:
31536000= one year (standard for production)63072000= two years (minimum for preload eligibility)0= revoke the policy immediately
Start shorter while testing. A week or month lets you roll back if something breaks. Once confident, extend to a year or more.
includeSubDomains extends protection to all subdomains. If example.com sends this directive, browsers enforce HTTPS for www.example.com, api.example.com, anything.example.com.
This is powerful but dangerous. If any subdomain doesn't support HTTPS, it becomes completely inaccessible. Audit every subdomain before enabling this.
Sending the Header
Configure your server to send HSTS on all HTTPS responses:
Nginx:
Apache:
Critical detail: browsers ignore HSTS headers received over HTTP. This prevents attackers from maliciously setting the policy—they'd need to compromise your HTTPS connection, at which point you have bigger problems.
HSTS vs. Redirects
Redirecting HTTP to HTTPS is necessary but insufficient.
With a redirect, the browser sends an HTTP request, your server responds with a redirect, then the browser makes the HTTPS request. That initial HTTP request is exposed.
With HSTS (after first visit), no HTTP request ever happens. The browser rewrites the URL internally before any network activity.
Use both: redirects catch first-time visitors and non-HSTS browsers. HSTS protects everyone who's visited before.
What HSTS Protects Against
Downgrade attacks: An attacker can't strip HTTPS from links or force HTTP connections. The browser refuses.
Session hijacking: Cookies can't leak over HTTP because HTTP connections don't happen.
User mistakes: Typing http:// or clicking old bookmarks doesn't matter. The browser fixes it silently.
SSL stripping: The classic attack where an attacker intercepts HTTP traffic and proxies to HTTPS becomes impossible after first visit.
Testing Your Setup
After deployment, verify HSTS works:
- Visit your site over HTTPS and check developer tools for the
Strict-Transport-Securityheader - Try visiting via HTTP—your browser should upgrade without any network request (visible in dev tools)
- Run your domain through SSL Labs or securityheaders.com for automated checking
Common Mistakes
Enabling includeSubDomains prematurely: One HTTP-only subdomain breaks everything. Audit first.
Setting max-age too long too soon: A two-year policy you can't roll back is painful if something breaks.
Sending over HTTP: The header gets ignored. Only HTTPS responses count.
Forgetting cached policies: When you change your HSTS configuration, users who haven't visited recently still have the old policy. Changes propagate slowly.
Revoking HSTS
If you need to disable HSTS, send:
Browsers that receive this clear their stored policy. But users who don't visit during this window keep the old policy until it naturally expires. There's no way to force-clear everyone's cache.
The Bigger Picture
HSTS is one layer in defense-in-depth security. It doesn't replace proper certificate management, secure coding practices, or other protections. It adds to them.
The elegance is in what it removes: the possibility of HTTP. After one successful visit, your users can't accidentally use an insecure connection even if they try. The browser has made a promise on their behalf, and it keeps it.
Frequently Asked Questions About HSTS
Was this page helpful?