How to roll out HSTS without breaking subdomains?

hsts_includesubdomains_unsafe_rolloutglobal

The HTTP Strict-Transport-Security header with the includeSubDomains directive forces browsers to use HTTPS for the domain and all subdomains. Once cached, this policy cannot be revoked by the browser. If any subdomain lacks a valid HTTPS configuration, it becomes unreachable until the max-age expires or the browser cache is manually cleared.

What’s Happening

The HSTS header includes the includeSubDomains directive. This instructs browsers to enforce HTTPS on the apex domain and every subdomain beneath it. The policy is cached for the duration specified in max-age. During that period, the browser refuses HTTP requests to any matching subdomain. If a subdomain does not support HTTPS or presents an invalid certificate, the browser blocks access entirely. There is no user override.

Why It Matters

Once the policy is delivered, it cannot be revoked by the server. A subdomain that is HTTP-only or misconfigured for HTTPS becomes completely inaccessible. This creates operational lock-in. Teams lose the ability to test subdomains, stage environments, or legacy services that were never migrated to HTTPS. Recovery requires waiting out the max-age or instructing users to manually clear browser security state. Neither option is acceptable at scale.

The Correct Change

  • Deploy HSTS in stages. Start with the apex domain only, without includeSubDomains. Set a short max-age initially.
  • Verify that every subdomain either supports HTTPS with a valid certificate or is not in use. This includes staging, development, API, CDN, and legacy subdomains.
  • Once all subdomains are confirmed reachable over HTTPS, add the includeSubDomains directive. Gradually increase max-age as confidence builds.
  • Do not add the preload directive until the policy has been stable across all subdomains for an extended period. Preloaded policies are enforced by browsers before any connection is made and cannot be revoked.

Verification

  • The Strict-Transport-Security header on the apex domain includes includeSubDomains only after all subdomains have been tested.
  • The max-age value starts low and increases incrementally.
  • Every subdomain responds successfully over HTTPS with a valid certificate.
  • No subdomain becomes unreachable after the policy is deployed.

Takeaway

  • The includeSubDomains directive applies the HSTS policy to the entire domain surface.
  • The policy is cached by the browser and cannot be revoked by the server.
  • A subdomain without HTTPS support becomes unreachable once the policy is cached.
  • Deployment must be staged, with verification of every subdomain before adding includeSubDomains.

FAQ

What happens if a subdomain does not support HTTPS when includeSubDomains is set?

The browser refuses to connect. The subdomain becomes unreachable until the HSTS max-age expires or the browser’s security state is manually cleared.

Can the policy be revoked after it is delivered?

No. The browser caches the policy for the duration of max-age. The server cannot instruct the browser to forget the policy.

Should staging and development subdomains support HTTPS before enabling includeSubDomains?

Yes. If they are accessible via browser, they must support HTTPS or they will be blocked once the policy is cached.

What is the correct initial max-age when rolling out HSTS?

Start with a short duration, such as 300 seconds or 3600 seconds. This allows rapid iteration and reduces the impact of misconfigurations.

What does the preload directive do?

It signals that the domain should be added to the browser’s HSTS preload list. Once preloaded, HTTPS is enforced before any connection is made. This cannot be undone quickly.

How can a team verify that all subdomains are ready for includeSubDomains?

Enumerate all subdomains in DNS and configuration. Test each subdomain’s HTTPS endpoint. Confirm that a valid certificate is presented and the connection succeeds.

The fix

Deploy HSTS incrementally to prevent subdomain lockout.

Done when: The Strict-Transport-Security header is deployed with includeSubDomains only after all subdomains have been verified to support HTTPS. The max-age value increases gradually as confidence in the configuration grows.

Do not

  • Do not add includeSubDomains before verifying all subdomains support HTTPS.
  • Do not start with a long max-age value.
  • Do not add the preload directive until the policy has been stable for an extended period.
  • Do not assume that unused subdomains are safe to ignore.

How to verify

  • The Strict-Transport-Security header is present on the apex domain.
  • The includeSubDomains directive is added only after all subdomains are verified.
  • The max-age value starts low and increases incrementally.
  • No subdomain becomes unreachable after the policy is deployed.

Find every page with this

probeo monitors this continuously across every page of your site, and records which pages passed, which failed, and which it could not determine.

Book a Call