emotion-js/emotion

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:

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

  2. 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:

  1. 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.
  2. 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
tkh44 commented

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!

tkh44 commented

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

@Spoonrad Did you ever find an answer to your query?

@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