What are HTTP security headers, and what is HSTS?
What do HTTP headers do?
Every time a browser asks for a page, it sends a request, and the server sends back a response. Headers ride along with both and let each side pass on extra information. In HTTP/1.x a header is a case-insensitive name, a colon and a value, for example Allow: POST. In HTTP/2 and later, developer tools show header names in lower case.
MDN groups headers by what they describe:
- Request headers describe the resource being fetched or the client asking for it, such as
Accept. - Response headers carry details about the response, such as its location, or about the server providing it.
- Representation headers describe the body, such as its MIME type with
Content-Typeor its compression withContent-Encoding. - Payload headers carry details such as
Content-Length.
Which headers count as security headers?
Security headers are response headers that tell the browser to apply extra protections to your site. MDN lists a security group that includes Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options, Permissions-Policy and the cross-origin policy headers.
MDN's practical implementation guides explain the purpose behind the most useful ones:
- Content Security Policy controls what code can load and run on a page, which helps reduce cross-site scripting.
- Clickjacking prevention controls how your site can be framed inside an
iframe. The CSPframe-ancestorsdirective sets which parents may embed a page. - Referrer policy limits what the
Refererheader leaks, which avoids exposing internal URLs. - MIME type verification makes sure resources are served with the correct type.
A simple starting policy that only allows resources from your own origin looks like this:
Content-Security-Policy: default-src 'self'One older header is worth removing rather than adding. MDN marks X-XSS-Protection as deprecated and non-standard, warns that it can create cross-site scripting problems on otherwise safe sites, and recommends Content Security Policy instead.
What is HSTS and how does it work?
HSTS stands for HTTP Strict Transport Security, sent with the Strict-Transport-Security header. It tells browsers to use only HTTPS for your domain. Once a browser has seen it, it upgrades any later http:// request to HTTPS automatically and will not let users click through certificate errors.
The header has three directives:
max-ageis required and sets how many seconds the browser remembers the rule.includeSubDomainsextends the rule to every subdomain.preloadopts the domain into browser preload lists. MDN says this needs amax-ageof at least 31536000 seconds, which is one year, plusincludeSubDomains.
MDN gives these example values:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadWhat should you check before turning on HSTS?
Browsers ignore the header if it arrives over plain HTTP, so it only works when sent over HTTPS. If your site still accepts HTTP, MDN says it should send a permanent redirect, such as a 301, to the HTTPS address, and that redirect should not carry the HSTS header.
HSTS does not protect the very first visit, because the browser only learns the rule after a secure connection. Preloading closes that gap by building your domain into the browser. Be careful with includeSubDomains and preload: every subdomain must work over HTTPS first. To switch HSTS off, send max-age=0 over HTTPS.
If you want to see which of these headers your site already sends, the AI Web Page SEO security audit checks your response headers and reports what it finds.
Sources
- MDN: HTTP headers
- MDN: Strict-Transport-Security
- MDN: Practical security implementation guides
- MDN: Content-Security-Policy
- MDN: X-XSS-Protection
Frequently asked questions
Should I still add the X-XSS-Protection header?
No. MDN marks X-XSS-Protection as deprecated and non-standard, and warns that it can create cross-site scripting vulnerabilities in otherwise safe websites. It recommends using Content-Security-Policy instead, noting that the old filtering is largely unnecessary when a strong policy disables inline JavaScript. You can remove the header from your server configuration.
How do I turn off HSTS if something breaks?
Send the Strict-Transport-Security header with max-age=0 over HTTPS. MDN explains that this only takes effect once a browser makes a secure request and receives the new value, because HSTS cannot be disabled over plain HTTP. Browsers that already stored the old rule keep it until they see the update, so test subdomains before using long values.