I have a React App using Create-React-App (react-scripts) and Material-UI. I would like to apply a strong Content-Security-Policy for my app which does not allow unsafe inline styles.
I would like to set the CSP-Header server-side with a nonce present which can be done easily. However, Material-UI sets certain inline <style>
tags dynamically at runtime without a nonce value as attribute.
I´ve seen the documentation on the Material-UI website under guides and csp. They seem to provide a solution. However, that solution is for server-side-rendering of the HTML, which I am not using. I am using Create-React-App and deliver the HTML, CSS and JavaScript statically.
Does anyone know how that can be achieved?
A nonce is a random number used only once per page load. A nonce-based CSP can only mitigate XSS if the nonce value is not guessable by an attacker. A nonce for CSP needs to be: A cryptographically strong random value (ideally 128+ bits in length)
You can enable a CSP in two different ways in a React app. The first is to add the headers directly to the response. The second is to add meta tags to the content. Note that meta tags aren't supported for some security headers, such as HSTS.
The JSS CSP docs explain this much better than the MUI CSP docs, and provide examples for Express and Webpack. Basically, you need to set the same "nonce" in a special <meta>
property called csp-nonce
(which is read dynamically by JSS) and in your Content-Security-Policy
header (either via another <meta>
or a HTTP header) of public/index.html
:
<meta http-equiv="Content-Security-Policy" content="default-src: 'self';
style-src: 'self' 'nonce-xxxxxxxxxxxxxxxx=='">
<meta property="csp-nonce" content="xxxxxxxxxxxxxxxx==" />
If you can do this dynamically in whatever serves your index.html
, then it is secure. (Obviously, an injected script could also read the nonce dynamically, but if that has happened, you've already lost). If you have to use a fixed value (e.g. because you're serving from a CDN), it's not secure but still arguably better than style-src: 'unsafe-inline'
, since an attacker at least needs to use your site-specific nonce.
As a hybrid approach when using a CDN, you can set a random nonce when the CDN fetches the page from the origin, as demonstrated here with an AWS Lambda@Edge. Then your nonce is only vulnerable in a specific region for the CDN cache TTL (which should be short for a mutable resource like index.html
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With