goober
goober copied to clipboard
CSP Nonce
We have a pretty strict CSP-Policy for our site and we would like to use a library which consumes goober
. The problem is that goober will inject styles directly to the document and if you have a CSP with pretty much anything other than 'unsafe-inline'
the browser will reject the insertion with an error that looks like:
Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 'nonce-xz5NmxIucN9byPuojlWd4'". Either the 'unsafe-inline' keyword, a hash ('sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='), or a nonce ('nonce-...') is required to enable inline execution.
I don't pretend to know every that would need to be implemented to solve this issue (and certainly not the consequences for making them).
However, I can say with certainty that the issue is this chunk of code: https://github.com/cristianbote/goober/blob/0f74be5079e01916158198d74c8e5872fa7b518c/src/core/get-sheet.js#L17-L20
Object.assign((target || document.head).appendChild(document.createElement('style')), {
innerHTML: ' ',
id: GOOBER_ID
})
At the very least the createElement
would need to be changed to:
document.createElement('style', { nonce })
The next question will be where does the nonce come from, which there could be several answers.
But before we get there, I'd like to do a quick reality check... Would this be a series of changes goober
is open / willing to make?
We are at an impasse right now with the library we want to use (it must be pulled out). So there are two options we can pursue:
- Get a change implemented in
goober
and then work the library author to consume that change - Just go a different direction (implement a different library)
What are people's thoughts?
I opened the issue above because I think it is a valid conversation, but there is a work around.
The saving grace is that goober
looks for a target container and if it doesn't find one, then it will create one. The saving grace is that it also generically looks at the window object for any id. This part:
https://github.com/cristianbote/goober/blob/0f74be5079e01916158198d74c8e5872fa7b518c/src/core/get-sheet.js#L16
What this means is if you're using React (in my case NextJS), you can do something like the following:
In your _document.tsx add the following element to your head:
<style
nonce={nonce}
id='_goober'
/>
This way, instead of goober
creating a new element, it will reuse one that already exists. And it also happens to have the nonce already. 🌈 🍯
Heya @jd-carroll if this is strictly related to NextJS than yeah it's kinda needed to have the style
element already defined. Check out the main example: https://github.com/vercel/next.js/blob/canary/examples/with-goober/pages/_document.js
I don't see how defining a
In full transparency, I don't think that solution works either and my grasp of how CSP-nonce works in NextJSv12 is/was pretty shaky.
At this point I've moved away from MUI (unfortunately) so this is no longer an issue. (Can't remember if goober was used by MUI or related library)
I'd also note from a NextJS perspective, the latest release finally has some support for CSP.
Hope that helps
The problem is not directly related Next.js or any other framework. If a web server delivers a CSP which does not allow inline styles, then goober fails. One way to allow inline styles is to use a "nonce". Other styling solutions offer support for this by offering an option to set the nonce or by getting the nonce for example from a well known meta tag.
In my particular case the lack of "nonce" support became a problem on update from Notistack v2 to v3 - there is already a ticket describing the issue there at https://github.com/iamhosseindhv/notistack/issues/552.
Can this issue please be addressed by the goober maintainers! This is really causing a lot of issues for users that have a strict CSP defined.
I don't see how defining a
https://github.com/cristianbote/goober/blob/0f74be5079e01916158198d74c8e5872fa7b518c/src/core/get-sheet.js#L17-L20 does use firstChild on the element found by that id (which is null for "style" elements).
The trick is to add some comment to the tag. Then it has a child and it works, somehow:
<style id="_goober" nonce="asd">
/* do not remove */
</style>