An HTTP to HTTPS redirect is useful. It is also easy to strip or rewrite on the first visit. HTTP Strict Transport Security (HSTS) tells the browser to remember that this host is HTTPS-only for a period of time, upgrade later http:// navigations before they leave the device, and refuse "click through" on certificate errors. The policy travels in the Strict-Transport-Security response header, and only over HTTPS (MDN, OWASP HSTS Cheat Sheet).
The six checks below tell you what to change on each host. The first, second, third and fifth checks only read headers every visitor already gets. The preload decision and the inventory of forgotten hosts need access to your own DNS and server config. Replace example.com with a host you own or have explicit permission to test.
1. Is Strict-Transport-Security on the HTTPS response?
curl -s -D headers.txt -o body.html https://example.com/ head -1 headers.txt grep -i '^strict-transport-security:' headers.txt Prefer a normal GET that keeps headers and body. Some servers answer HEAD differently from GET. Confirm you got a real document, not an error page or a redirect whose headers belong to another hop.
Add the header on the HTTPS response. RFC 6797 says hosts must not send it over plain HTTP, and browsers ignore it if they see it on HTTP, so a network attacker cannot plant or shorten a policy that way. A meta http-equiv for HSTS is also ignored (RFC 6797 section 8.5).
If the header is missing on the main entry host, first-time visitors and browsers whose remembered policy has expired will start with an insecure hop again. A redirect to HTTPS is not a substitute: without this header, the browser has nothing to remember.
2. What does max-age say?
max-age is required. It is a number of seconds from when the browser receives the header. Common production values are on the order of months to a year or two (for example 31536000 for one year). Each fresh HTTPS response that carries the header refreshes the clock (MDN).
| Value you see | What to do |
|---|---|
| No header | Add Strict-Transport-Security on the HTTPS response. |
max-age=0 | This deletes the remembered policy for this host, once the browser gets it over HTTPS. Use it only when you intend to unwind HSTS. |
| Small max-age (minutes or a few days) | Fine for a careful rollout. Raise it once HTTPS is stable on every host the policy will cover. |
| Large max-age | Keep emitting the header on later visits so the clock refreshes. Plan how you would send max-age=0 if you ever need to unwind, because browsers keep the old policy until it expires (RFC 6797 section 8.6). |
3. Did you mean includeSubDomains?
for h in example.com www.example.com api.example.com; do printf "%s " "$h" curl -s -o /dev/null -D - "https://$h/" | grep -i '^strict-transport-security:' || echo "(none)" done includeSubDomains extends the policy to hosts under the issuing name. That helps when cookies are scoped to the parent domain, but it also means every subdomain the browser might hit must speak proper HTTPS or users get hard failures (RFC 6797 section 11.4, OWASP).
Before you turn it on, inventory internal or forgotten hosts (dev., legacy., a tool on an alternate port) and put them on HTTPS, or leave includeSubDomains off until they are ready.
Emit the header on each well-known entry host, not only on the apex. Sending it only on example.com while everyone bookmarks www.example.com leaves many browsers without a policy until they hit the apex (RFC 6797 section 11.4.2, MDN).
4. Preload: first-visit gap versus a long commitment
HSTS does not protect the very first HTTP visit to an unknown host: that request can still be downgraded or watched on the wire. Browser preload lists (Chromium's list is widely reused) close that gap for submitted domains (Chromium HSTS, hstspreload.org).
Preload is not in RFC 6797. To be accepted through hstspreload.org, a site must serve a valid certificate; redirect from HTTP to HTTPS on the same host if port 80 is open; serve HTTPS on every subdomain, including www when that name has DNS; and send a base-domain header that includes max-age of at least one year (31536000), includeSubDomains, and preload. If HTTPS itself redirects, that redirect response must still carry the HSTS header. The example header on the preload site uses two years:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload hstspreload.org recommends enabling HSTS and does not recommend preloading. Many browsers already upgrade HTTP navigations to HTTPS on their own, so preload mainly helps when those upgrades fail against an active attacker. Inclusion is hard to unwind quickly across browser updates. Do not ship preload by default in config generators.
If you want first-visit protection, submit the domain at hstspreload.org and confirm it appears on the list. The preload token in a header is a request for inclusion, not confirmation that any browser has shipped the name.
5. Same policy on the paths that matter?
for p in / /login /account /static/app.js; do printf "%s " "$p" curl -s -o /dev/null -D - "https://example.com$p" \ | grep -i -E '^(HTTP/|strict-transport-security|location):' || true echo done # Plain HTTP should redirect; STS must not appear on the insecure response curl -s -o /dev/null -D - http://example.com/ \ | grep -i -E '^(HTTP/|location|strict-transport-security):' If a homepage sends HSTS and an API or login host does not, add the header on the HTTPS responses that are missing it. CDNs, app servers, and object stores often disagree.
On HTTP, send a permanent redirect to https and do not include Strict-Transport-Security on that insecure response; put the header on the HTTPS follow-up (MDN, OWASP Transport Layer Security Cheat Sheet).
6. What to pair with the header
RFC 6797 does not address phishing on another domain, or malware on the user's machine. After the header is in place, still:
- review TLS configuration, certificate expiry, and mixed content (see the OWASP TLS Cheat Sheet);
- mark session cookies
Secure, so they are not sent on a plain HTTP request; - decide whether preload is worth closing the first-visit gap;
- treat a compromised origin as a separate problem: the browser will still talk HTTPS to an attacker-controlled server that has a valid certificate for that name.
A sensible Strict-Transport-Security header means browsers that have seen it will prefer HTTPS and refuse easy certificate bypass for that host. It does not mean the rest of the application is safe.
We are the HackerMe team, and we build a free scanner that reads public response headers. You can run it on a domain you own or have explicit permission to test at https://hackerme.ai.
Sources
- IETF, RFC 6797, HTTP Strict Transport Security (HSTS): https://www.rfc-editor.org/rfc/rfc6797
- MDN, Strict-Transport-Security: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security
- OWASP, HTTP Strict Transport Security Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Strict_Transport_Security_Cheat_Sheet.html
- OWASP, Transport Layer Security Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html
- Chromium, HTTP Strict Transport Security: https://www.chromium.org/hsts/
- HSTS Preload List Submission: https://hstspreload.org/


