Content Security Policy (CSP) in Create-React-App (CRA)
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
.