The includeSubDomains directive looks harmless. You add one token to your Strict-Transport-Security header, the certificate scanners give you a green tick, and your security scorecard goes up. What the token actually does is far broader than most people expect: it extends the HTTPS-only rule from the exact host that sent the header to every subdomain beneath it, forever, for anyone whose browser has seen the header once. That reach is the whole point — and also the trap.
What the directive really promises the browser
When a browser receives Strict-Transport-Security: max-age=31536000; includeSubDomains from example.com, it stops treating that as a statement about one host. It records a policy for the entire tree: www.example.com, api.example.com, shop.example.com, and any host you have never even provisioned yet. From that moment, until max-age expires, the browser will refuse to make a plain HTTP request to any of them. It rewrites http:// to https:// internally before a packet leaves the machine.
Crucially, an HSTS failure is not a warning you can click through. If a subdomain cannot complete a valid HTTPS handshake — no certificate, an expired certificate, a self-signed certificate, or simply a service that only ever listened on port 80 — the browser shows a hard error with no bypass button. The user cannot proceed. The subdomain is, for practical purposes, off the internet for anyone who has visited your apex.
The subdomains you forgot you owned
The danger is rarely your public marketing site. It is the long tail of hosts that grew up outside the main deployment pipeline and never got TLS:
- Legacy internal tools on
tools.example.comorintranet.example.com, reachable over HTTP because "it is only on the office network". - A staging or demo box on
dev.example.comserving a snapshot with no certificate. - A marketing microsite or event page parked on a third-party host that only speaks HTTP.
- Appliance and device panels — printers, cameras, NAS boxes, router admin — sitting behind an internal DNS name.
- A blog or docs subdomain delegated to a SaaS provider that has not been configured for custom-domain HTTPS.
None of these send the HSTS header themselves, so a naive audit of the apex misses them entirely. But includeSubDomains on the apex speaks for all of them. The first time an employee or customer loads your main site over HTTPS, their browser quietly arms the policy, and the next time they try to reach that HTTP-only tool it fails with an unbypassable error.
Preload turns the trap into a snare
With dynamic HSTS, at least the policy only applies to people who have already visited you. preload removes even that grace period. The hstspreload.org list bakes your domain — and includeSubDomains is a hard requirement for the list — directly into the browser binary. Now the policy is active on a first-ever visit, for users who have never touched your site, and it ships to hundreds of millions of installs. A forgotten HTTP-only subdomain does not just break for returning visitors; it breaks for everyone, and, as covered in our guide to removing a domain from the preload list, undoing that decision takes months.
Inventory every host before you flip the switch
The fix is boring and effective: know what you own before you make a promise about all of it. Pull the full picture from several angles, because no single source is complete.
- Your DNS zone. Export the authoritative zone file and list every A, AAAA and CNAME record. This is your ground truth for what resolves.
- Certificate Transparency logs. Query a CT aggregator such as crt.sh for
%.example.com. Because every publicly trusted certificate is logged, CT often surfaces subdomains that never made it into your own documentation. - Reverse proxy and load-balancer config. Virtual-host blocks reveal names that answer even without a dedicated DNS record.
- Delegated and vendor hosts. Anything pointing at a third party needs its HTTPS story confirmed on their side, not yours.
For each host, confirm it serves a valid, trusted certificate and answers on 443. A quick way to verify the handshake, chain and expiry for a given name is TLS Studio; to sanity-check the certificate itself — issuer, SANs, validity window — use SSL Studio. A wildcard certificate covers many of these at once, but note that a wildcard only helps a host that is actually configured to present it; a device on port 80 with no HTTPS listener is still broken regardless of what certificate you hold.
Roll out in stages, not in one commit
Treat includeSubDomains as the last step of a sequence, not the first.
- Header on the apex only, short lifetime. Start with
Strict-Transport-Security: max-age=300— noincludeSubDomains, nopreload. This protects the main host while committing you to nothing you cannot walk back in five minutes. - Bring every subdomain onto valid HTTPS. Work through the inventory. Retire dead hosts, add certificates to the live ones, and fix the vendor-hosted stragglers.
- Add includeSubDomains, still short. Only once the tree is genuinely HTTPS-clean, add the directive with a modest
max-ageand watch your error dashboards for a real user cycle. - Ramp the lifetime. Grow
max-agetowards a year in steps — see what value to actually use — so a mistake never locks visitors in for longer than you can tolerate. - Preload last. Submit to the list only when you are confident the whole tree will stay HTTPS-only indefinitely.
The order matters because HSTS is a promise you make to browsers you cannot recall. includeSubDomains broadens that promise to every host you own and several you have forgotten. Inventory first, fix second, and let the directive be the reward for work already done — not the event that reveals what you missed.