13
votes

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?

2
Create React App doesn't support Server Side Rendering, you may check Next.jsGabriel Bleu
I don't want Server Side rendering.Stefan
I've set the <meta property="csp-nonce" content="123456" /> in the <head> element as described on the Material-UI website under guides and csp, but the new <style> element that are added at runtime in the browser do not include the nonce, but look like this: <style type="text/css" data-jss data-meta-"MuiInputLabel" nonce>. The nonce attribute is there in the '<style>' tag but it has no value. Could anyone solve that?Stefan
How do you generate a new nonce on each request to index.html if you are only serving your site statically?Saad

2 Answers

1
votes

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).

0
votes

It works the way it is. The nonce value is set, even though it is not shown in the browser.