Content-Security-Policyheaders from inline script and style hashes
When running things like Gatsby or Gridsome, the initial state is stored inside a
Modern browser content security policies don't like inline scripts or styles, so to get around it you need to add either a cryptographic nonce or a cryptographic hash of each script.
A nonce is out of the question, because you can't update it for each load.
This package generates a crypographic hash (SHA-256) of all inline scripts and styles in each HTML file, and adds it to the
_headers file along with other policies of your choice.
Netlify lets you add a
Content-Security-Policyheader in your
netlify.toml. This will overwrite values inside
_headers, so don't do that.
If you have an existing
_headers file, this will append to the existing file. Just make sure the file ends on a newline, and it should work fine.
netlify-plugin-csp-generator with your favourite package manager:
yarn add netlify-plugin-csp-generator npm install netlify-plugin-csp-generator
netlify.toml file, add an additional plugin:
[[plugins]] package = "netlify-plugin-csp-generator" [plugins.inputs] buildDir = "dist" [plugins.inputs.policies] defaultSrc = "'self'"
buildDiris the path for the publish directory in Netlify:
excludeis an array of paths you don't want to include. It defaults to an empty array.
disablePoliciesis an array of policies to never include. Files that need these rules will probably be taken from
defaultSrcinstead by your browser.
disableGeneratedPoliciesis an array of policies never to generate. Use this to turn off default policies but still allow the key in
reportOnlygenerates headers with
Content-Security-Policy-Report-Onlyinstead, which is useful for testing.
reportTosends violations to a given endpoint. See Reporting violations for more information.
generateForAllFileslets you generate headers for non-HTML files. See Non-index.html files for more information.
You can use the following policies:
Add them under the
[plugins.inputs.policies] object in your
netlify.toml file, with your specified value in quotes.
You can use CSP headers not in this list too - simply use the name in camel case and it will be added.
When using Vue and derivatives (like Gridsome), you may want to use
v-show on things. This adds an inline style of
display: none;, which is forbidden by CSP Level 3. To prevent this throwing an error, you need to add
'unsafe-hashes' to your
styleSrc policy. The
sha-256 hash is generated automatically.
[[plugins]] package = "netlify-plugin-csp-generator" [plugins.inputs] buildDir = "dist" [plugins.inputs.policies] defaultSrc = "'self'" styleSrc = "'unsafe-hashes'"
What is generated
If you have defined a policy in your
netlify.toml file, this will be added to all files.
[plugins.inputs.policies] defaultSrc = "'self'" scriptSrc = "'self' https://www.google-analytics.com https://ssl.google-analytics.com https://www.googletagmanager.com"
/each-file-path/ Content-Security-Policy: default-src 'self'; script-src 'self' *.google-analytics.com;
If a file includes a
<style> tag with content, this file path will have the hash added:
/file-with-no-script/ Content-Security-Policy: default-src 'self'; /file-with-script/ Content-Security-Policy: default-src 'self'; script-src 'sha256-RFWPLDbv2BY+rCkDzsE+0fr8ylGr2R2faWMhq4lfEQc=';
If a file has any inline styles, these will be hashed:
/file-with-inline-style/ Content-Security-Policy: style-src 'unsafe-hashes' 'sha256-0EZqoz+oBhx7gF4nvY2bSqoGyy4zLjNF+SDQXGp/ZrY='
Generally, routes are generated with an
index.html file, like
/some/file/path/index.html. However, sometimes you need to handle HTML files that aren't called 'index', for example
404.html in Nuxt.
These are generated as wildcard links and are placed above the non-wildcard paths in your
_headers file (for specificity):
/*.html Content-Security-Policy: default-src 'self'; script-src 'sha256-Qb2XxXiF09k6xbk2vTgHvWRed+mgYYGzFqZ6dShQVA0='; /specific-path/ Content-Security-Policy: default-src 'self';
Any matching wildcard URL has the hashes joined together - for example, if you have a
404.html and a
500.html with scripts/styles, all the hashes will be merged together under
In general, it is better to generate
generateForAllFiles setting, you can generate route keys that use
/* instead of
/*.html. Be careful, this will send Content-Security-Policy headers for every file type (i.e.
.css, etc) which is redundant as per the spec.
The Content-Security-Policy specification allows for reporting violations to a URL - you can read more about it on MDN.
This is useful for testing and checking directives.
To set the header to report only, set
reportOnly = true in your
netlify.toml alongside your policies.
[plugins.inputs] reportOnly = true reportURI = "/report-csp-violations-to-this-uri"
reportOnlyto true will NOT enforce your policy
- You need to add
Using the report-to directive
reportURI is deprecated in CSP Level 3 in favour of
report-to. To use the report-to directive, set the
reportTo value to the group name as defined in the
Reporting-Endpoints header that you also need to set.
[plugins.inputs] reportOnly = true reportTo = "csp-violations-group"
- You can include
reportOnly = true, and the policy WILL be enforced and errors will also be reported
- You can set both the
reportURIdirectives - this is recommended to ensure maximum compatibility
Help it's all broken!
Oh, you. Chances are your browser console is screaming at you, and the network tab is showing a lot of
See our list of example policies to get started.
unsafe-inlineeverything, because that will make CSP redundant. If in doubt, ask Google, Stackoverflow, or create a Github issue (in that order).
If you found this plugin useful, or are just feeling nice, feel free to donate!