Improving Security of Gatsby Websites and Apps by Implementing a Strict CSP

As a website and business owner, it is of utmost importance to be aware of the security issues that might affect your website, users, and business-like having insecure software. According to the OWASP, Cross-Site Scripting (XSS) is the second most prevalent issue in the Top 10 Application Security Risks and is found in around two-thirds of all applications. XSS is a common type of vulnerability that allows an attacker to inject malicious code into a website.

Those simple snippets of code can be programmed to do pretty much anything. They do simple tasks as show unwanted images but can also be used for mining cryptocurrencies or showing those dreaded pop-ups.

By default, a browser is allowed to load all dynamic resources like images, CSS, and scripts from every origin. If an attacker injects malicious code into some of your resources it can not only damage your website but potentially corrupt your users as well and hurt your business.

[@portabletext/react] Unknown block type "newsletter", specify a component for it in the `components.types` prop

What is a Content Security Policy?

Content Security Policy also is known as CSP helps reduce Cross-Site Scripting (XSS), clickjacking, and other code injection attacks. Its goal is to prevent loading untrusted assets from unknown origins and is widely supported by most modern web browsers.

NEW IFrame for Content Security Policy Level 2 data.

We developed the gatsby-plugin-csp to help you add a strict policy to your Gatsby websites and apps. In case you need a less strict policy, you can edit the directives in gatsby-config.js file.

Declaring strict rules provide extra protection for your visitors by defining what your browser is allowed to load and what should be blocked.


The complete list of all directives you can find on the MDN web docs

By default, gatsby-plugin-csp includes these directives:

base-uri 'self';
default-src 'self';
script-src 'self' 'sha256-iF/...GM=' 'sha256-BOv...L4=';
style-src 'self' 'sha256-WCK...jU=';
object-src 'none';
form-action 'self';
font-src 'self' data:;
connect-src 'self';
img-src 'self' data:;

Inline Scripts and Styles

It's a good idea to block inline scripts completely, however, Gatsby needs a couple of inline scripts to work properly. Those scripts are a bit different with each build. You can whitelist them by including a sha-256 hash to the script-src directive. Gatsby-plugin-csp does it automatically for you. You can disable it in the config options.

The same is accurate for styles, the plugin takes inline styles located in the head and creates hashes for them. That does not apply for inline styles in the HTML tag attribute.

Gatsby-image issue

Gatsby-image uses inline styles in style attributes (as opposed to inline <style> elements). According to the CSP specification, hashes should apply to inline <style> elements only, not to style attributes. It means that Gatsby-image needs unsafe-inline to work properly, which is against our default strict policy. You can change this by editing the directive in gatsby-config.js

Policy Delivery

You can deliver CSP in two ways. First, and a preferred way is an HTTP response header Content-Security-Policy. The second way is to implement a policy directly on a page in the markup using a <meta> tag with an http-equiv attribute.

Our plugin implements the policy through a <meta> tag. The reason is that we don't know which hosting provider you will use. Each of them configures the HTTP headers a bit differently. Firebase needs a .firebase file, Vercel uses a now.json, Netlify has a _headers file and so on and so forth.

We decided to use a <meta> tag to support all hosting providers. There is an open issue to extract directives somehow for other plugins' usage, but I can't guarantee when that happens.