DEV Community

marcellothearcane
marcellothearcane

Posted on

How to CSP your Netlify projects

TLDR: I made this Netlify plugin for CSP. You should give it a try.


Have you ever seen the full fury of dev tools spitting blood/blocked:csp at you?

Alt Text

No? Well you should have. Because that means you have at least tried to set up a Content-Security-Policy on your website before.

Setting up a content security policy is essential for preventing XSS attacks - which is a big deal, because XSS was responsible for 40% cyber attacks in 2019.

However, it's not always fun to set up. If you're using something like Gridsome on Netlify, you will come across two key issues that you can't solve just by adding a Content-Security-Policy key to the headers in your netlify.toml.

  1. Gridsome (and Gatsby) inline the initial state, which is a big <script></script> block.
  2. Vue uses inline styles for v-show, like style="display:none;"

Both of these things are blocked by CSP rules, which is good because you don't want random scripts being added into your website or your styles being messed up (someone styling another link as a 'pay now' button for example).

To fix this, you need to generate a cryptographic hash of the inline script, so the browser knows this is okay and hasn't been tampered with. If you search online, you might find some bad advice, like using unsafe-inline. (Bad! Bad! saith the buyer...)

If you're using Netlify, you can use this amazing package I made earlier to generate sha256 hashes of inline scripts and styles for your Content-Security-Policy headers. Head over to the Github repo, and try it out on your Netlify project.

GitHub logo MarcelloTheArcane / netlify-plugin-csp-generator

Generate CSP headers from inline script hashes

netlify-plugin-csp-generator

NPM codecov CodeQL

Generate Content-Security-Policy headers from inline script and style hashes

When running things like Gatsby or Gridsome, the initial state is stored inside a <script> tag 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.

Note
Netlify lets you add a Content-Security-Policy header 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…

If you're not using Netlify, you're on your own. Sorry about that.


Want to check your website for XSS vulnerabilities? Just run this in your browser console:

const script = document.createElement('script')
script.innerHTML = 'alert("hacked!")'
document.body.appendChild(script)
Enter fullscreen mode Exit fullscreen mode

This website is safe from XSS

This website is not safe from XSS

😱

Discussion (0)