Security Headers

HSTS explained: why HTTPS alone is not enough

The gap HTTPS leaves open

You installed a certificate and your site runs on HTTPS. Good — but there is still a soft spot. When a user types yoursite.com without the scheme, or follows an old http:// link, the browser makes that first request over plain HTTP before any redirect to HTTPS happens. In that brief window, an attacker on the same network can intercept the request and keep the user on a fake HTTP version of your site — a downgrade attack. HTTPS protects the encrypted connection; it does nothing about the unencrypted request that started it.

What HSTS does

HSTS (HTTP Strict Transport Security) is a response header that tells the browser: for this site, never use HTTP again — always go straight to HTTPS. Once the browser has seen the header, it rewrites any http:// request to your domain into https:// before it even leaves the machine. The vulnerable first request disappears, and so does the downgrade attack.

Reading the header

A typical strong value looks like this:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

  • max-age — how long, in seconds, the browser should remember to force HTTPS. 63072000 is two years, a common recommendation. Longer is stronger.
  • includeSubDomains — extends the rule to every subdomain, so app.yoursite.com and api.yoursite.com are covered too.
  • preload — lets your domain be baked into browsers' built-in HSTS lists, so HTTPS is forced even on the very first visit, before the browser has ever seen your header.

The preload catch

Preload is the strongest option and the one to approach carefully. Getting onto the preload list is easy; getting off it is slow and propagates to users gradually. And includeSubDomains plus preload means every subdomain must serve HTTPS — including ones you forgot about. If an internal or legacy subdomain is HTTP-only, preload will break it. So turn on includeSubDomains and preload only when you are confident every subdomain is HTTPS-ready; until then, a long max-age on its own already removes the downgrade risk for repeat visitors.

Common mistakes a scan catches

  • No HSTS at all — the most common state; the downgrade gap is wide open.
  • A tiny max-age — a few minutes or hours barely helps; the protection only lasts as long as the browser remembers.
  • Missing includeSubDomains — your main domain is forced to HTTPS but a vulnerable subdomain is not.

Check your HSTS

HSTS is invisible from the page, and a too-short or missing value looks identical to a correct one from the outside. An automated scan reads the actual header and flags a missing HSTS, a weak max-age, or a missing includeSubDomains. Scan your site and confirm the downgrade gap is closed.

Related reading

FAQ

If I already redirect HTTP to HTTPS, do I still need HSTS?
Yes. The redirect itself travels over plain HTTP on that first request, which is exactly where a downgrade attack strikes. HSTS makes the browser skip the HTTP request entirely, so there is nothing to intercept.
What max-age should I use?
A long one — two years (63072000 seconds) is a common strong choice. The protection only lasts as long as the browser remembers, so short values like minutes or hours give little real benefit.
Is preload safe to enable?
It is the strongest option but the hardest to reverse, and with includeSubDomains it requires every subdomain to serve HTTPS. Enable preload only once you are sure all subdomains are HTTPS-ready; otherwise start with a long max-age and add preload later.