How to set up HSTS on Netlify
Tags: webdev, javascript, programming, tutorial
Published: 2023-09-02 13:05:37

## What is HSTS and why should you care?

### HSTS helps make your website more secure.

HSTS, stands for “HTTP Strict Transport Security” which adds extra security to HTTPS websites. It protects websites against man-in-the-middle attacks and cookie hijacking.

Note: This is more secure than simply configuring a HTTP to HTTPS (301) redirect on your server, where the initial HTTP connection is still vulnerable to a man-in-the-middle attack.

For a full description, check out [Wikipedia's HSTS page](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security).

## How to check whether a website is on Google’s HSTS Preload list

You can check if a site is using HSTS or not at Google’s [HSTS Preload](https://hstspreload.org/) website.

Or

The presence of the HSTS header can be confirmed by examining the server’s response through an intercepting proxy or by using curl as follows:

    $ curl -s -D- https://yourdomain.com | grep -i strict

You should see the result below, if you haven't setup HSTS yet continue reading.

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

Curl information source: [owasp.org](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/07-Test_HTTP_Strict_Transport_Security)

### Before adding HSTS to this site, I saw the following results:

> Status: travislord.xyz is not preloaded.
>
> Eligibility: In order for travislord.xyz to be eligible for preloading, the errors below must be resolved:
>
> Error: No includeSubDomains directive
> The header must contain the includeSubDomains directive.
>
> Error: No preload directive
> The header must contain the preload directive.

When I saw that, of course I wanted to add HSTS. Here’s how I did it.

## How to make most websites hosted on Netlify eligible for Google’s HSTS preload list

If you don't already have one create a netlify.toml file in your root directory. Now head to the file and add the following lines.

    [[headers]]
      for = "/*"
      [headers.values]
        Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload"

Max-age of 63072000 is two years. Google’s minimum is one year, but it appears that Netlify wants two and Netlify includeSubDomains running.

[Netlify HSTS preload - Doc ](https://docs.netlify.com/domains-https/https-ssl/#hsts-preload)

Committed, pushed and time to see if it worked! 🤞

Now head back to Google’s HSTS Preload to check the site again, you should see something similar to the following example. [Link](https://hstspreload.org/)

> Eligibility: travislord.xyz is eligible for the HSTS preload list.

**You should see a “submit” button, followed by the following agreement request:**

> I am the site owner of travislord.xyz or have their permission to preload HSTS. (If this is not the case, travislord.xyz may be sending the HSTS preload directive by accident. Please contact hstspreload@chromium.org to let us know.)
>
> I understand that preloading moonbooth.com through this form will prevent all subdomains and nested subdomains from being accessed without a valid HTTPS certificate:
> \*.travislord.xyz
> _._.travislord.xyz …

**You should see a “submit” button, followed by the following agreement request:**

> Success
> travislord.xyz is now pending inclusion in the HSTS preload list!
>
> Please make sure that moonbooth.com continues to satisfy all preload requirement, or it will be removed. Please revisit this site over the next few weeks to check on the status of your domain.
>
> Also consider scanning for TLS issues using [SSL Labs](https://www.ssllabs.com/ssltest/index.html).

If you check you site again on hsts preload you will now see the message under the 'Check HSTS preload status and eligibility' button.

> Status: travislord.xyz is pending submission to the preload list.

Now it's a waiting game, come back in a few weeks and you will see the status like below.

> Status: travislord.xyz is currently preloaded

## Bonus round

### X-Frame-Options

    X-Frame-Options = "DENY"

### X-XSS-Protection

    X-XSS-Protection = "1; mode=block"

### Content-Security-Policy

Replace domain.com with the sites domain.

    Content-Security-Policy = " font-src cdnjs.cloudflare.com fonts.gstatic.com domain.com"

### X-Content-Type-Options

    X-Content-Type-Options = "nosniff"

### Permissions-Policy

    Permissions-Policy= "vibrate=(), geolocation=(), midi=(), notifications=(), push=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), speaker=(), vibrate=(), fullscreen=(), payment=()"

### Referrer-Policy

    Referrer-Policy = "strict-origin-when-cross-origin"

Cheers for coming this far, take it all 🍻

    [[headers]]
      for = "/*"
      [headers.values]
        Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload"
        X-Frame-Options = "DENY"
        X-XSS-Protection = "1; mode=block"
        Content-Security-Policy = " font-src cdnjs.cloudflare.com fonts.gstatic.com yourdomain.com"
        X-Content-Type-Options = "nosniff"
        Permissions-Policy= " midi=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(), payment=()"
        Referrer-Policy = "strict-origin-when-cross-origin"

To test the extra headers you can head over to [securityheaders.com](https://securityheaders.com/). You should see the same results displayed on the image under the blogs title. 

[**Want to read more**...](https://travislord.xyz/articles)