Configuring Security Headers with Netlify
There is a set of standard HTTP headers that every website should implement to ensure a basic level of security. In this note, I’ll cover these headers and how to set them up for sites deployed on Netlify.
Common Security Headers
First, let’s review the basic HTTP headers — these are general for all requests and provide a foundational layer of security.
Content-Security-Policy Header
This helps protect your website from Cross Site Scripting attacs by providing a list of approved content. This header restricts the use of content that doesn’t comply with the rules or shouldn’t be part of your site’s content. Configuring this header can seem complex, so if you want to dive deeper, check the official site. Example usage:
Content-Security-Policy: default-src 'https://example.com'; script-src 'unsafe-inline' 'https://example.com'; style-src 'unsafe-inline' 'https://example.com'; object-src 'none'
X-Frame-Options Header
This tells the browser whether your site can be displayed in an iframe or not. In most cases, you’ll want to disallow this, as it prevents your site from being used for Clickjacking attacks. The concept is simple: a visitor sees your site’s page and clicks a button. In reality, there is another transparent page layered on top, and the visitor clicks a button on that page instead. Example usage:
X-Frame-Options: DENY
X-XSS-Protection Header
In older browsers (mainly Safari), this header protects your site from XSS attacs. Most browsers recognize this header and will stop loading the page when they detect such attacks. Example usage:
X-XSS-Protection: 1; mode=block
X-Content-Type-Options Header
This prevents the browser from analyzing and modifying the MIME type of the content. This type of attack checks the content stream to try and identify the file format inside and inject additional data. Example usage:
X-Content-Type-Options: nosniff
Referrer-Policy Header
This controls how much referrer information is sent when the browser accesses your site from another domain. Essentially, this header manages the amount of referrer data included in requests. Example usage:
Referrer-Policy: same-origin
Strict-Transport-Security Header
This protects your site from being redirected to unsecured protocols. It tells browsers to always connect to your site using HTTPS and never over HTTP. Example usage:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Permissions-Policy Header
This informs browsers about which features (e.g., geolocation, camera, microphone) are allowed or restricted on your website. Example usage:
Permissions-Policy: geolocation=(), gyroscope=(), magnetometer=()
Content-Security-Policy Header
Content Security Policy (CSP) is used to determine whether a content being loaded in the page is from a trusted source or not. CSP is versatile in controlling all different kinds of content from which script gets loaded to what a form target can be set to through its various directives, and hence protects your users from a wide range of attacks such as clickjacking attacks and cross-site scripting attacks. Example usage:
Content-Security-Policy: script-src 'self' www.googletagmanager.com;
Setting Up Headers in Netlify
There are two ways to set headers in Netlify: by adding them to the Netlify configuration file (netlify.toml
):
[[headers]]
for = '/*'
[headers.values]
X-Frame-Options = 'DENY'
X-XSS-Protection = '1; mode=block'
X-Content-Type-Options = 'nosniff'
Referrer-Policy = 'same-origin'
Permissions-Policy = '''
accelerometer=(),
camera=(),
geolocation=(),
gyroscope=(),
magnetometer=(),
microphone=(),
payment=(),
usb=(),
interest-cohort=()
'''
Content-Security-Policy = """
script-src 'self';
form-action 'none'
"""
Strict-Transport-Security = '''
max-age=31536000;
includeSubDomains;
preload
'''
or by using a separate _headers
file:
/*
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
X-Content-Type-Options = "nosniff"
Referrer-Policy = "same-origin"
Content-Security-Policy = "script-src 'self'; form-action 'none'"
Permissions-Policy = "accelerometer=(), camera=()"
Permissions-Policy = "geolocation=(), gyroscope=()"
Permissions-Policy = "magnetometer=(), microphone=()"
Permissions-Policy = "payment=(), usb=(), interest-cohort=()"
Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
Note: Netlify supports repetitions within the _headers
file. For instance, the following example:
/path
example: one
example: two
Will behave the same as:
/path
example: one, two
Conclusion
Setting security headers should give your website an “A” rating on services like securityheaders.com, and using them wisely will make security testers respect your site’s level of protection.
Configuring a Content Security Policy depends on the specific website and can vary, for instance, if you use Google Analytics or other third-party scripts. Keep in mind that when implementing any security policy, you should thoroughly test your site to ensure that all third-party resources and clients still function correctly.
References
- HTTP Security Response Headers Cheat Sheet
- Content Security Policy Cheat Sheet
- Content Security Policy Reference
- MDN: Content Security Policy (CSP)
- Security Headers
- MDN: X-Frame-Options
- MDN: X-XSS-Protection
- MDN: X-Content-Type-Options
- MDN: Referrer-Policy
- MDN: Strict-Transport-Security
- Permissions Policy