HSTS preload broke the staging subdomain
A step-by-step skill for fixing staging hosts broken by HSTS preloading: confirming preload status, serving staging over valid HTTPS, and requesting removal when needed. Use when a staging subdomain becomes unreachable in browsers after the parent domain is preloaded. Triggers: 'HSTS preload', 'staging HSTS', 'preloaded HSTS subdomain'. Not for: plain HSTS header misconfigurations, cert errors on non-preloaded domains, or local dev HSTS cache issues.
HSTS preload broke the staging subdomain
TL;DR
Preloading applies HSTS to the whole domain including every subdomain, so a staging host without a valid cert becomes unreachable in modern browsers. Short term, serve staging over proper HTTPS. Long term, either accept preloading everywhere or request removal and wait months.
HSTS preload broke the staging subdomainUse this when
- A staging subdomain stops loading in browsers after the parent domain was preloaded
- There's no click-through past the certificate warning
- The same staging host works in curl with -k but not in any browser
- A new subdomain is unreachable from day one
Not for this skill when
- The domain was never preloaded (that's a plain HSTS header issue, removable instantly)
- The problem is local dev HSTS cache (clear the browser's HSTS entry)
- The cert error is on a non-preloaded domain
Steps
- Confirm preload status:
curl -s "https://hstspreload.org/api/v2/status?domain=example.com"Expected: a status of preloaded. If it's preloaded, every subdomain inherits the policy.
- Check what staging serves:
curl -sI https://staging.example.com | head -3Expected: if the TLS handshake fails, browsers will hard-fail too; there is no click-through on preloaded HSTS.
- Immediate fix: give staging a valid certificate (a real one from your CA, or the same wildcard as production) and serve it over HTTPS with a redirect from http.
Expected: staging loads in Chrome, Firefox, and Safari with no warnings.
- If you truly need a non-HTTPS staging host, submit a removal request at the preload list's removal page. Then wait: removal propagates via browser preload lists, which update on browser release cycles, so budget months, not days.
Expected: the status API eventually shows removed; browsers pick it up on their own schedule.
- Decide the durable policy: either every subdomain gets HTTPS always (recommended; keep preload) or keep staging off the preloaded domain entirely (staging-example.com instead of staging.example.com).
Expected: a written call so the next staging host doesn't repeat this.
Variant: HSTS broke local dev
That's not preload; clear the browser's HSTS cache for the domain, or use a dev domain that was never preloaded.
Variant: preload inherited from a parent company's domain
You can't fix the parent. Move your hosts to a domain you control or serve them all over HTTPS.
Variant: includeSubDomains set without preload
Same breakage, but removable instantly by changing the header. Preload is the one-way door; the header alone is not.
Why this happens
The preload list bakes your HSTS policy into the browser itself, with includeSubDomains semantics. It's a one-way door by design: easy to enter, slow to leave, because the security property depends on browsers remembering it.
Edge cases and pitfalls
- Removal requests need to be deliberate; browsers won't fast-track you.
- Test staging in a fresh browser profile to rule out cached HSTS confusing the diagnosis.
- Don't fix this by telling the team to bypass the warning with a flag; the flag doesn't scale and the habit leaks into production thinking.
- Wildcard certs plus preload are a fine combination; the cert just has to actually cover staging.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_IhE0BDqiNMgIG7lCuFHvHQ