Content Security Policy (CSP) in Create-React-App (CRA)

Nima Shahri
Jan 25 · 3 min read

Writing suitable CSP policy may requires some changes to your app build pipeline to fetch and calculate hashes for inline scripts and styles, which are used. CRA is one of the build tools which I am using in different projects.

I am trying to add some inline scripts for Google Analytics and Hubspot. Also I prefer to keep runtime js as inline script. I decided to use CSP-2 and use <Meta> to define CSP policies for my app.

No inline script or style

By default, Create React App will embed an inline script into index.html during the production build.

This is a small chunk of webpack runtime logic which is used to load and run the application. The contents of this will be embedded in your build/index.html file by default to save an additional network request.

You can set INLINE_RUNTIME_CHUNK environment variable to false, the script will not be embedded and will be imported as usual.

The following <meta> element can be added as a first element to HTML <head> to activate CSP and force to run only JS and CSS from the same source as the page.

<meta http-equiv="Content-Security-Policy" content="script-src 'self'; style-src 'self'; ..." >

Using inline script or style

You may want to show some beautiful content to user when the app loading or it may be faster to use runtime JS as inline script.

You can add unsafe-inline CSP policy to allow all inline styles and scripts.

Banning inline script is the biggest security win CSP provides, and banning inline style likewise hardens your application. It’s a little bit of effort up front to ensure that things work correctly after moving all the code out-of-line, but that’s a tradeoff that’s well worth making

CSP 2 offers backward compatibility for inline scripts by allowing you to whitelist specific inline scripts. This can be done by using either a nonce or a hash.

As nonces must be regenerated for every page request and it is not part of build process so my focus in this article is to use hash.

Install dependencies

$ npm install react-app-rewired customize-cra csp-html-webpack-plugin --save-dev

‘Flip’ the existing calls to react-scripts in npm scripts

"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test"

Add config-overrides.js file in the root directory

const {override} = require('customize-cra');
const cspHtmlWebpackPlugin = require("csp-html-webpack-plugin");

const cspConfigPolicy = {
'default-src': "'none'",
'base-uri': "'self'",
'object-src': "'none'",
'script-src': ["'self'"],
'style-src': ["'self'"]
};

function addCspHtmlWebpackPlugin(config) {
if(process.env.NODE_ENV === 'production') {
config.plugins.push(new cspHtmlWebpackPlugin(cspConfigPolicy));
}

return config;
}

module.exports = {
webpack: override(addCspHtmlWebpackPlugin),
};

Update index.html

Add <meta>as first child element to <head> on index.html in public folder

<meta http-equiv="Content-Security-Policy" content="">

Build

Run npm run build to generate production build at you should be able to see this change in production index.html file:

<meta http-equiv="Content-Security-Policy" content="base-uri 'self'; object-src 'none'; script-src 'self' 'sha256-GgRxrVOKNdB4LrRsVPDSbzvfdV4UqglmviH9GoBJ5jk='; style-src 'self'">

FAQ

Q: Do I need to add unsafe-inline to script to style CSP policy?

A: I only recommend to use it when there is any online script or style in your project and you want to support browsers which are only supporting CSP-1. CSP-2 will ignore unsafe-inline policy when any hash or nonce exists in a policy.

Q: How can I access the sample source?

A: https://github.com/NShahri/cra-csp-sample

Q: What about workers?

A: worker-src is a CSP Level 3 directive that restricts the URLs that may be loaded as a worker, shared worker, or service worker. I expected this directive has limited implementations.

The deprecated child-src directive defines the valid sources for workers and frames. I recommend to use frame-src and worker-src directives.

CSP Html header can be used on related JS file to apply separated CSP policy to workers.

More to read

Nima Shahri

Written by

Full stack web developer. React, NodeJS, .Net

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade