HTTPS and HSTS: closing the plain-HTTP gap
Having a certificate is not the same as being HTTPS-only. As long as the plain HTTP address answers, and the browser is not told to stop using it, the first request of a visit can be read and rewritten.
Example
HTTP/1.1 200 OK ← http://example.com/ serves the page
(no redirect, no HSTS on the HTTPS version)HTTP/1.1 301 Moved Permanently
Location: https://example.com/
# on every HTTPS response:
Strict-Transport-Security: max-age=31536000; includeSubDomainsWhere it leaks
A visitor typing example.com or following an old http:// link makes a cleartext request first. If that answers with content instead of a redirect, an attacker on the network can serve whatever they like. Even with a redirect, without HSTS that first hop is open to SSL stripping. On HTTPS pages, scripts or images loaded over http:// are blocked or can be swapped.
How to fix it
Three steps, in order.
- Redirect every http:// request to https:// with a 301
- Send Strict-Transport-Security: max-age=31536000; includeSubDomains on HTTPS responses
- Load every resource over https:// and add upgrade-insecure-requests to the CSP
- Automate certificate renewal and alert well before expiry
How RepoVerse finds it
- HighSite is served over plain HTTP
Everything between the visitor and the server — pages, form fields, cookies — can be read and changed by anyone on the network path: public Wi-Fi, an ISP, a compromised router.
website · CWE-319
- ModerateThe HTTP address does not redirect to HTTPS
A visitor who types the address without `https://`, or follows an old link, gets an unencrypted page that an attacker on the network can rewrite before they ever reach the secure version.
website · CWE-319
- ModerateNo HSTS header
Without `Strict-Transport-Security` the browser will still try plain HTTP for typed addresses and old links, which leaves room for an SSL-stripping attack on the first request.
website · CWE-319
- LowHSTS lifetime is short
The browser forgets the HTTPS-only rule quickly, so visitors who come back after the max-age has passed are exposed on their first request again.
website · CWE-319
- HighTLS certificate is not trusted
Browsers show a full-page warning. Visitors who click through can no longer tell your server from an impostor's, which is exactly what an interception attack needs.
website · CWE-295
- ModerateHTTPS page loads resources over HTTP
Browsers block insecure scripts, styles and frames on an HTTPS page, so those parts break; where they do load (images, media) they can be swapped on the network.
website · CWE-319
Questions
- What HSTS max-age should I use?
- At least 15552000 seconds (180 days); a year (31536000) is common. Start lower while testing, and add includeSubDomains only once every subdomain serves HTTPS.
- Should I submit my site to the HSTS preload list?
- Only when you are sure every subdomain will stay on HTTPS: preloading is hard to undo. Add the preload directive and submit at hstspreload.org once the policy has run without problems.
Related
- Secure session cookies: the flags and the login stepSet session cookies safely: Secure, HttpOnly and SameSite flags (CWE-614, CWE-1004), regenerating the session at login against fixation, with Express examples.
- Content Security Policy: writing one that actually protectsWrite a Content-Security-Policy that actually stops XSS: why unsafe-inline, unsafe-eval and wildcard sources defeat it, nonces and strict-dynamic, and a policy to start from.
- Security headers checker with a fix for every gapCheck a site's HTTP security headers — Content-Security-Policy, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy — and get the exact line to add for each gap.
Updated 2026-10-11