Use a strong HSTS policy

Plaintext protocols such as HTTP can be vulnerable to eavesdropping attacks where an attacker is able to read the transmitted content. Luckily, Transport Layer Security (TLS) can encrypt the traffic and make it significantly harder for attackers to use this data if captured.

However, it is possible for attackers to circumvent TLS by forcing encrypted connections to use plaintext HTTP. To address this problem, the HTTP Strict Transport Security (HSTS) response header was introduced which forces the user's browser to visit a website only using TLS and not fall back to plaintext HTTP (for a set time).

How the Lighthouse audit fails

Lighthouse audit warning that no HSTS response header was found.
Lighthouse report warning that no HSTS response header was found.

The audit will flag the following issues with the HSTS header:

  • If there is no HSTS header found at all.
  • If one of the recommended directives is missing (max-age, includedSubDomains, preload)
  • If the duration for the max-age directive is under one year (31536000 seconds).
  • If there a syntax error when parsing the header, such as an unknown directive.

Configure a strong HSTS policy

The optimal HSTS header configuration looks as follows:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • The max-age directive specifies the amount of time the user's browser is forced to visit a website only using TLS (in seconds). After that time, it will be possible to reach the site using plain HTTP again if there is no HSTS header provided by the website (or temporary redirects from HTTP to HTTPS are in place).
  • Setting the includeSubDomains directive will enforce the header on any subdomains of the page URL sending the header initially. For example, having an HSTS header sent by google.com which includes the includeSubDomains directive would also enforce the HSTS header on mail.google.com.
  • Setting the preload directive and submitting the domain to the HSTS preload service will compile the domain into browser binaries that use the preloaded HSTS list (not just Google Chrome).

There are some risks when rolling out the HSTS header. Any features that require an unencrypted HTTP connection would effectively be broken for the time set in the max-age directive. Potentially even longer if the preload directive is applied.

To lower risks associated to the rollout, a staged approach is recommended:

  1. Starting with a small max-age and only add includeSubDomains (no preload):

    max-age=3600; includeSubDomains
    
  2. After some cooldown period (e.g., one week) with no reported issues, raise the max-age, for example:

    max-age=604800; includeSubDomains
    
  3. If this initial phase is successful for an extended period of time (e.g., three months), the website and its subdomains should be added to the HSTS preload list and the preload directive should be added.

    max-age=63072000; includeSubDomains; preload