Support Forums

Define strict-transport-security Header Cause Duplicate Headers

When using a custom domain, netlify will generate a certificate and add “strict-transport-security: max-age=31536000” header to http response by default, which is really great and secure. However, I was trying to add my website to HSTS Preload List (https://hstspreload.org), and it requires “strict-transport-security: max-age=xxx; includeSubDomains; preload”. So I tried to set them based on the official document https://docs.netlify.com/domains-https/https-ssl/#hsts-preload .
Here’s my netlify.toml:

  for = "/*"
    strict-transport-security = "max-age=63072000; includeSubDomains; preload"

Unfortunately, it results two strict-transport-security headers in the HTTP response, one is the default one added by netlify, and the other one is added based on my netlify.toml. As a result, it fails the requirement of HSTS Preload List because there are multiple strict-transport-security headers, and the curl -I result looks like this:

strict-transport-security: max-age=31536000
strict-transport-security: max-age=63072000; includeSubDomains; preload

I think this should be considered as a bug becuase:
This is a programming/configuration error. RFC 7230 (Section 3.2.2) says:

A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list [i.e., #(values)] or the header field is a well-known exception (as noted below).

It also says:

A recipient MAY combine multiple header fields with the same field name into one “field-name: field-value” pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma.

In fact the Invoke-WebRequest (powershell) will interpretation the above headers as:

Strict-Transport-Security: max-age=31536000,max-age=63072000; includeSubDomains; preload

Which is not a valid syntax and HSTS policy won’t apply based on RFC 6797 (Section 6.1)

So my best guess is, the strict-transport-security in netlify.toml should overwrite the default header provided by netlify, or they should be combined to a single header with valid syntax before send out?

Try to use Strict-Transport-Security instead of strict-transport-security. It help for me.