Missing HTTP Strict Transport Security
CWE-319CWE-523OWASP A04:2025Updated October 2, 20265 min read
HTTP Strict Transport Security instructs the browser to reach a site over HTTPS only. If the header is missing, or its lifetime is set to a few days, an attacker on the same network can force the first request back to HTTP and intercept or alter the traffic before encryption ever begins.
Virtually every site runs on HTTPS these days, and current browsers try HTTPS first even when someone types an address without a protocol, clicks an old link, or follows a bookmark from years ago. But when that attempt fails, they fall back to an unencrypted request, at most after a warning the user can click past. That fallback is exactly what an attacker waits for, because they can make the attempt fail themselves. This article covers how HSTS closes that window, and which settings go wrong.
What is HTTP Strict Transport Security?
HTTP Strict Transport Security (HSTS) is an HTTP header with which a server instructs the browser to reach this domain over HTTPS only from now on. The browser remembers that instruction for the given period and from then on converts every http:// address for this domain to https://, before a single byte goes onto the network.
The difference from an ordinary redirect is subtle but decisive. A redirect is a response from the server: the browser therefore has to send an unencrypted request in order to hear that it should switch to HTTPS. HSTS is an instruction the browser remembers: no unencrypted request is sent to find out that it should not have been allowed.
Picture a reception desk where visitors have to show their passport. A redirect is the receptionist saying: “you are inside now, but please walk back and check in properly.” HSTS is the sign outside that visitors had already read before they walked in. In the first case, someone has already stood in the hall; in the second, they have not.
How does a downgrade attack work?
The attack takes place on the network: a public wifi network, a compromised router, or an intermediate provider. The attacker does not have to break encryption, only prevent it from ever being established.
Vulnerable:
HTTP/1.1 301 Moved Permanently
Location: https://portal.example/login
On the face of it this is correct: the server neatly forwards visitors to HTTPS. The problem is that in order to receive this response, the user first had to send the following:
GET /login HTTP/1.1
Host: portal.example
A current browser first tries HTTPS on its own, but an attacker sitting in between simply blocks that attempt, and the browser then falls back to this request, which travels across the network in readable form. The attacker never lets the redirect arrive. Instead they maintain the connection with the user over HTTP themselves, speak HTTPS with your server at the back, and read along with everything the victim types: username, password, session cookie. The user sees a working login page and at most notices that the padlock is missing.
Safe:
HTTP/1.1 200 OK
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
After one successful HTTPS visit the browser remembers this for a year. If the user then types portal.example in the address bar, the browser sends an HTTPS request straight away; there is no unencrypted request left to intercept. includeSubDomains extends that rule to every subdomain, which matters because a forgotten test.portal.example would otherwise remain an open side door. With preload, and once you submit the domain at hstspreload.org, it joins a list included in the browser itself, so even the very first visit is protected.
includeSubDomains once you are certain that every subdomain supports HTTPS, including internal test environments and supplier systems. A subdomain that only runs HTTP becomes unreachable for all visitors after this setting, and the browser remembers that for the full lifetime.What is the impact of missing HSTS?
The severity is usually rated low to medium, because the attacker needs a position in the network path. That condition is less demanding than it sounds: a public network on a train, in a hotel or a café, a spoofed wifi access point, or a compromised home device will do.
If the attack succeeds, the damage is complete. The attacker reads everything that crosses the connection: credentials, session cookies, personal data and the contents of forms. They can also alter the response, which opens the way to a fake login screen or injected script code. Because the session cookie is captured in that scenario, the attacker does not even need to know the password to continue.
A max-age that is too short weakens the protection without removing it entirely. If the value is 30 days, a user who has not visited for six weeks is vulnerable again on their next visit, which is precisely the moment they type the address once more.
How do you detect missing HSTS?
The check starts with the HTTPS response: is there a Strict-Transport-Security header, and if so, how long is the max-age? A value under a year is a point of attention, and a value of zero actively disables the protection.
Then comes the investigation that scanners usually skip. Is the header set on subdomains too, or does includeSubDomains cover domains that offer no HTTPS themselves? Does the HTTP version of the site forward correctly to HTTPS, and does it land on the right path? Is the header accidentally set only on the home page and not on the API or the login endpoint? And is the domain on the preload list while a subdomain without a certificate still exists? During a penetration test AssistSec checks the full certificate chain and redirect structure, and assesses whether any path remains along which a user can still speak to your application unencrypted.
How do you prevent missing HSTS?
- Send
Strict-Transport-Securityon every HTTPS response, withmax-age=31536000as a guide value. - Add
includeSubDomainsonce you are sure all subdomains support HTTPS. - Build up the lifetime in phases: start short, verify that everything works, then raise it to a year.
- Keep forwarding HTTP to HTTPS; HSTS complements that redirect rather than replacing it.
- Consider joining the preload list for domains that run permanently and fully on HTTPS.
- Never set the header on an unencrypted response; browsers ignore it there, which gives a false sense of security.
- Automate certificate renewal, for example through ACME, and monitor expiry: with HSTS visitors can no longer click past a certificate error, and publicly trusted certificates have been valid for at most 200 days since 15 March 2026, falling to 100 days in 2027 and 47 days in 2029.
- Configure the header centrally in your web server or proxy, so new hosts and routes inherit it automatically.
Sources
Frequently asked questions
Is a redirect from HTTP to HTTPS not enough?
No, because that redirect itself travels unencrypted. An attacker between user and server can intercept that first request and replace the response, so the browser never arrives at the HTTPS version. The redirect is still needed, but HSTS is what stops an unencrypted request from being sent at all.
Which max-age should I set?
The common norm is 31536000 seconds, or one year. Shorter values such as 30 days occur regularly and are better than nothing, but they shrink the window in which the browser remembers the rule. When in doubt, build up: start with a few minutes, check that everything works, and raise it step by step to a year.
What does the preload option do?
With preload, and once you submit it at hstspreload.org, your domain joins a list baked into browsers themselves. The browser then knows before the very first visit that your site is reachable over HTTPS only, which protects the opening request too. Be careful: removal from that list takes months, so do this only if every subdomain supports HTTPS permanently.
Can HSTS make my site unreachable?
Yes, and that is the reason for a careful rollout. Once a browser has remembered the rule, it refuses every unencrypted connection for the remaining lifetime. If your certificate expires or a subdomain only serves HTTP, visitors cannot click past it. Test with a short max-age first.
Related articles
- VulnerabilitiesCWE-327A04:2025Cryptographic failuresCryptographic failures explained: MD5 for passwords, ECB mode, hardcoded IVs and home-grown crypto, and why Argon2id and AES-GCM are the fix.
- VulnerabilitiesCWE-319A04:2025Insecure transport and weak TLSInsecure transport explained: plain HTTP, missing HSTS, outdated TLS versions and cookies without Secure, and how to enforce HTTPS everywhere.
- VulnerabilitiesCWE-16A02:2025Security misconfigurationSecurity misconfiguration explained: how default passwords, debug modes and open cloud buckets let attackers in, and how to harden your systems.
- VulnerabilitiesCWE-1004A07:2025Unprotected authentication cookieA session cookie without HttpOnly, Secure and SameSite is readable, interceptable and abusable. Learn what each attribute actually covers.