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. Transport Layer Security (TLS) can encrypt the traffic and make it significantly harder for attackers to use this data if captured.

However, it's possible for attackers to circumvent TLS by forcing encrypted connections to use plaintext HTTP. To address this problem, you can use the HTTP Strict Transport Security (HSTS) response header. HSTS forces the user's browser to visit a website using TLS, and doesn't allow it to 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 flags 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, includeSubDomains, 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). Once the time lapses, users can reach the site with plain HTTP againm if there is no HSTS header provided by the website (or temporary redirects from HTTP to HTTPS).
  • Setting the includeSubDomains directive enforces the header on any subdomains of the page URL sending the header initially. For example, having an HSTS header sent by google.com that includes the includeSubDomains directive would 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. This is true for more than 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 (such as 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 (such as 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