Travis lord Logo
How to Secure Your Netlify Site with HSTS đź”’

How to Secure Your Netlify Site with HSTS đź”’

3 min read

Published on: Sun Jun 02 2024

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.

More about HSTS by: Dev Mozilla

From my understanding, this is more secure than simply configuring an 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.

How to check if a website is on the

HSTS Preload list

You can check if a site is using HSTS or not at Google’s HSTS Preload website.

Or

The presence of the HSTS header can be confirmed by using curl as follows:

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

You should see the result below, if you have set up HSTS. If you dont see this yet continue reading.

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

Curl information source:owasp.org

From what I have found, by default, Netlify automatically sets this up.
- Custom headers on Netlify can be set using their Docs and Answers, which were helpful to me.

Before adding HSTS to a Netlify site, I saw the following results:

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

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.

How to add HSTS to a Netlify Site or App

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

After you have published the updated netlify.toml

Head back to Google’s HSTS Preload to check the site again, you should see something similar to the following example.

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.

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

Essential HSTS Headers for Enhanced Security

X-Frame-Options

X-Frame-Options = "DENY"

X-Frame-Options prevents the website from being framed or embedded into other websites, protecting against clickjacking attacks.

X-XSS-Protection

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

Enables the cross-site scripting (XSS) filter built into most web browsers and instructs the browser to block the page if an XSS attack is detected.

Content-Security-Policy

Replace domain.com with the site domain.

Content-Security-Policy = " font-srccdnjs.cloudflare.comfonts.gstatic.comdomain.com"

Helps prevent a wide range of attacks, including cross-site scripting (XSS) and other code injection attacks, by specifying which dynamic resources are allowed to load.

X-Content-Type-Options

X-Content-Type-Options = "nosniff"

Prevents browsers from interpreting files as a different MIME type than what is specified in the Content-Type header, helping to reduce the risk of certain types of attacks, such as drive-by downloads.

Permissions-Policy

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

Controls which browser features can be used by the website, helping to enhance security and privacy by restricting access to potentially sensitive APIs such as geolocation, camera, and microphone.

Referrer-Policy

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

Controls how much referrer information is included with requests made from your site, enhancing privacy and security by limiting the amount of information shared about the origin of requests.

Remember to customize all headers according to your site's specific requirements.

[[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.

Thank you for reading until the end.
Before you go please consider supporting by giving a Hart, Share, or Follow! 👏

Share On Social: