Supporting locked down CSP environments.
Closed this issue · 7 comments
We run a pretty locked down content security policy in production, which doesn't allow for "unsafe-inline" style tags. This blocks both inserted <style>
tags or the style
attribute on elements.
I think the solution for this that would work for us (and others like us) would be to use the nonce directive. In this setup, the server supplies a nonce in the CSP header, and any inline <style>
tags that use it will be allowed to run, e.g: <style nonce="some-nonce">
.
I think there are two options for this:
-
Do what styled-components did: styled-components/styled-components#887 and https://github.com/styled-components/styled-components/pull/1022/files here the containing page sets window.webpack_nonce (somehow) to match the nonce in the header. And emotion would set the attribute on the tags it inserts.
-
The alternative would be to have the containing page create a style tag with the nonce already set, and emotion could reuse that as mentioned: https://twitter.com/tkh44/status/918901965924397057
I think either is roughly equivalent from an end user point of view. When deployed to production the http server will have to inject the nonce either in a js script, or into the style tag into index.html which is roughly equivalent.
I am tempted to suggest that option 1. would help spread awareness/usage of webpack_nonce and allow the same setup work in either lib, but I personally am not too strongly wedded to either (and obviously I don't know the internals of emotion.
NB to cover two potential concerns:
- The issue raised here about IE11 is a red-herring - IE11 will ignore all the csp rules regardless, so it doesn't need to be worked around.
- I made a test page to confirm that CSP rules won't block the modification of existing stylesheet rules, looks like they do not: https://gist.github.com/latentflip/61b3102a90c31999664b6e4933a55d0e
Wouldn't option 2 be easier for everyone involved and also work for those not using webpack.
I think you can actually do this now without any modifications.
Very first thing in your app
import { sheet } from 'emotion'
sheet.tags[0] = document.getElementById('MyEmotionSheet')
This should work. I haven't tested it though.
Wouldn't option 2 be easier for everyone involved and also work for those not using webpack.
Yes you may be right about that.
And yeah that’s cool that it’s already supported!
@latentflip Keep in mind this is only a solution in "speedy" or production mode. While in development mode emotion will create a new style tag for each style so this won't work.
Hi there,
Our React project uses emotion/core, emotion/styled and emotion-theming. We're looking to use a CSP that rejects unsafe inline styles, but I am unsure how to implement the nonce approach. Could you please give clear guidelines for a noob? Happy to supply additional info if needed. I can open another issue if wanted. Thanks a lot.
@weyert I think (but I'm not an expert in this regard) that you have to generate nonce per request and provide it to your client-side's JS - from there it should be easy to just use that nonce through CacheProvider component
Check out the docs here: https://emotion.sh/docs/@emotion/cache#nonce