What this means
The Strict-Transport-Security response header, defined in RFC 6797, makes a browser remember that your site is HTTPS only for the number of seconds in max-age. During that time it rewrites http:// requests to https:// before sending them and refuses to let users click through certificate errors. If the header is missing, a redirect from http to https is your only protection, and that first plain request can be intercepted on a hostile network.
Why it happens
- Frameworks do not send HSTS by default, and generated projects rarely add security headers.
- The app sits on a custom server, container or proxy where nobody configured response headers.
- The header is set on the www host but not on the bare domain, or the other way round.
- The header is sent over http only. Browsers ignore HSTS on insecure responses, so it must be on the HTTPS response.
How to fix it
- 1Confirm your whole site, and every subdomain you use, works over HTTPS with a valid certificate. includeSubDomains applies to all of them, including ones you forgot.
- 2Add the header in your framework or hosting config, starting with a short max-age such as 300 seconds.
- 3Browse the site and its subdomains. If nothing breaks, raise max-age in stages to one year (31536000).
- 4Keep the http to https redirect. HSTS works alongside it.
- 5Only add the preload directive and submit to hstspreload.org if you are sure. Preloading requires max-age of at least one year with includeSubDomains, and removal is slow.
module.exports = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains',
},
],
},
];
},
};
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" }
]
}
]
}
/*
Strict-Transport-Security: max-age=31536000; includeSubDomainsHow to confirm the fix
Request your own site over HTTPS and read the headers. Check both the bare domain and www. You can also open devtools, click the main document in the Network tab and look under Response Headers.
curl -s -D - -o /dev/null https://yourapp.com | grep -i strict-transport-security
curl -s -D - -o /dev/null https://www.yourapp.com | grep -i strict-transport-security
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://yourapp.comFrequently asked questions
My host already forces HTTPS. Do I still need HSTS?
Yes. A redirect only helps after the first insecure request has been sent. HSTS removes that request for returning visitors. Some hosts add the header for you, so check your response headers before adding a second copy.
What max-age should I use?
One year, 31536000 seconds, is the common target and the minimum for the preload list. Ramp up to it in stages as hstspreload.org recommends.
Should I preload my domain?
Only when every current and future subdomain will support HTTPS. Preloading protects the very first visit, but it is a long-term commitment.