-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add __webpack__nonce to style tags #887
Comments
This seems like a very reasonable thing to implement! @sokra @TheLarkInn can you confirm that |
I guess there are no docs for it yet. But if you add docs for it it probably stays supported. Here is the PR for the feature: webpack/webpack#3210 |
Unfortunately, nonce attributes are not supported in ie11 Is there any known workaround for avoiding such CSP violations as this in ie11? |
I would love more discussion on this. PCI Compliance audits can mandate the need to have a CSP that prohibits using awesome libraries like this, or worse, having to remove them to pass compliance :-/ |
I would also love to see more discussion on this. My current setup with a strict Inserting a static nonce with webpack seems like a bad idea as well. If all style elements have the same nonce everywhere everytime, this would defeat the whole purpose of having a nonce. |
We implemented support for |
We have a working solution, maybe @stnwk can give you Insights about it.
(I'm currently in parental leave)
…On Feb 1, 2018 11:41, "Max Stoiber" ***@***.***> wrote:
We implemented support for __webpack-nonce__ back in July, what else are
you looking for @mindhaq <https://github.com/mindhaq>?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#887 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAlR-_bXF-GVln6hJIsVlQbJdpR_vugdks5tQZTIgaJpZM4Nzynv>
.
|
@johannesnagl can you point me at that working solution? I can't get this working.
this means the nonce generated on the server and injected into the template can be picked up by the react app entry point. The nonce is getting picked up from the style tag, but webpack isn't picking up the webpack_nonce value. |
This is our implementation! /* global __webpack_nonce__ */ // eslint-disable-line no-unused-vars
// CSP: Set a special variable to add `nonce` attributes to all styles/script tags
// See https://github.com/webpack/webpack/pull/3210
__webpack_nonce__ = window.NONCE_ID; // eslint-disable-line no-global-assign, camelcase In our layout file, which is served via PHP, we have the following, simplified code (above the script tag with the webpack-bundle of course): <script nonce="<?= $currentNonce ?>">window.NONCE_ID = '<?= $currentNonce ?>';</script>
<script src="HERE_COMES_YOUR_BUNDLE.js"></script> |
I think it has to be before any imports. Since imports are hoisted, you'll have to create a separate file ( |
thanks @mxstbr, that did it 👍 |
@simonkerr would you like to share the full setup with everyone, so that the next dev coming here has a better time then you had? #developerlove |
@johannesnagl where would you suggest the best place to do that? I'm writing a blog post at the moment about all this stuff and was thinking of updating the webpack docs for nonces. |
@simonpkerr Fixing the nonce docs is definitely needed - so +1 for this! Regarding my comment: I would just paste a small code example here. Nevertheless, if you write a blog post, feel free to add the link here too! |
So...in your server-side code you set up the nonce and expose it to your client-side code before any other scripts are defined
In your entry point file, import your 'create-nonce.js' file before any files that reference styled components.
Then in 'create-nonce.js' grab the global NONCE_ID variable...
Webpack will now add the nonce attribute to any injected script or style tag on a per request basis. |
@simonpkerr |
@isaacOstler My (possibly incorrect) understanding is that the current nonce is always available in the content security policy header (e.g. |
@johannesnagl Are there any examples of this working with next.js? I am absolutely stuck at #887 (comment) |
@TheoMer sorry, don't have any experience with next.js! |
@mxstbr Any ideas on implementing this with next.js? |
I still cannot get this to work. I have the following html: <style nonce="w51UFM0uev/LhCA+J2h7Bw==" data-styled="" data-styled-version="4.3.2">
/* sc-component-id: sc-global-140695928 */ And the following header:
I will get a lot of these errors:
I don't understand why it is not working because the nonces are the same. It only works when I use |
I managed to solve my problem by adding this to the html: Notice the nonce on the script tag as well. You may need this if you also used a csp directive that disallows inline scripts. <script nonce="w51UFM0uev/LhCA+J2h7Bw==">window.__webpack_nonce__ = "w51UFM0uev/LhCA+J2h7Bw==";</script>
|
@sebastiaandegeus doesn't the above negate the purpose of the nonce? Any scripts / styles injected client side would probably be able to read |
I am not 100% sure, this is my understanding of it: It seems that stealing the nonce is already a point of discussion in the spec: As far as I understand injected scripts would not be executed if the nonce is not set. For example a comment in your comment section that contains a script tag. It will not be executed if the nonce is wrong and it cannot get the nonce because it is blocked right away. I was digging through the code and found this: https://github.com/styled-components/styled-components/blob/147b0e9a1f10786551b13fd27452fcd5c678d5e0/packages/styled-components/src/utils/nonce.js Which is used here to add a nonce to the stylesheet:
This is happening client side so it has to get the nonce from somewhere, which at that point had to be made available in a javascript variable or DOM. Maybe one of the maintainers can shed some light on this issue? |
@sebastiaandegeus yeah I think it makes sense. In order to read the nonce from the global variable the page would have already have to have been exploited. |
Could you at least add a section to your docs about the caveats of this library in combination with a strict CSP? I had to search and read for hours and I still don't completely get what is supported and what isn't. It now seems to me you can only get it working with server side rendering. Is that correct? |
@wzijden - it all depends on your nonce settings. But it short - in a strict mode you have to provide And question - why one is actually need CSP for styles? |
For example, we use nginx and inject nonce in CSP headers and meta tag with property csp-nonce which is then used by material-ui. |
To the next person trying to get this to work: the code suggested by @johannesnagl in #887 (comment) and @simonpkerr in #887 (comment) does work, but not in development. |
This may be an odd case that only applies to us, but I want to point out how I got it working. The styled components code to get the nonce normally looks like this: var getNonce = function getNonce() {
return typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null;
}; But after looking at the real source and not just the sourcemap, I saw this: var getNonce = function getNonce() {
return true ? __webpack_require__.nc : undefined;
}; After some digging, it seems that webpack will replace references to __webpack_require__.nc = window.__webpack_nonce__; Remember that it has to be in a module, because EDIT: I want to point out that this is the same solution that simonpkerr demonstrated. The difference is that we want to set |
@gordonkristan can you elaborate on this please? can you bring example similar like @simonpkerr thank you for your help! |
Sorry to comment on a closed issue, but has anyone had any luck using this with NextJS and styled-components? I am getting Refused to apply inline styles errors when using styled-components with my content-security-policy. My solution so far is listed below, but the nonce does not appear to be working. NextJS + styled-components nonce issueimport Document, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
import { randomBytes } from 'crypto'
const prod = process.env.NODE_ENV === 'production'
const inlineScript = (body, nonce) => (
<script type='text/javascript' dangerouslySetInnerHTML={{ __html: body }} nonce={nonce} />
)
function getCsp(nonce) {
let csp = ``
if (prod) {
csp += `default-src 'self' 'nonce-${nonce}' data: https://*.myDomain.net https://*.amazonaws.com https://amazonaws.com;`
csp += `script-src 'self' 'self' 'nonce-${nonce}' data: https://*.myDomain.net https://*.amazonaws.com https://amazonaws.com;`
csp += `style-src 'self' 'nonce-${nonce}' data: https://*.myDomain.net;`
}
return csp
}
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
const nonce = randomBytes(8).toString('base64')
const csp = getCsp(nonce)
const res = ctx?.res
if (res != null) {
res.setHeader('Content-Security-Policy', csp)
}
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />)
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
nonce,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
}
} finally {
sheet.seal()
}
}
render() {
const { styles, nonce } = this.props
return (
<Html lang='en' dir='ltr'>
<Head nonce={nonce}>
{inlineScript(`window.__webpack_nonce__="${nonce}"`, nonce)}
{styles}
</Head>
<body>
<Main />
<NextScript nonce={nonce} />
</body>
</Html>
)
}
} |
I already had a brief talk with @mxstbr about this a couple of weeks ago: https://twitter.com/mxstbr/status/824626370760364032
When trying to enforce strict rules about which content is allowed on a specific page, a Content Security Policy (CSP) is the way to go.
Styled-Components currently put all of their Styles as an inline style to the DOM. Therefore, a CSP would need to contain: style-src
unsafe-inline
. As the name already puts: This is unsafe and not the recommended way of securing your app.Luckily, there is the concept of
nonce
attributes. Style/Script tags with a whitelistednonce
can be specified in the CSP. If Styled-Components would set thisnonce
, we could get rid of theunsafe-inline
setting.Luckily, WebPack is already supporting the concept of a global
__webpack_nonce__
variable. Once set, all dynamically injected code created by WebPack will have a nonce attribute with the correct value.What needs Styled-Components to do?
If the webpack_nonce variable is set, pass the value to every generated style tag inside the
nonce
attribute of thestyle
tag.Unluckily, the
__webpack_nonce__
is not well documented and kind of amyth
. See Google https://www.google.at/search?q=webpack_nonce__&oq=webpack_nonce__&aqs=chrome..69i57.4663j0j7&sourceid=chrome&ie=UTF-8#q=__webpack_nonce__ and GitHub: https://github.com/webpack/webpack/search?utf8=%E2%9C%93&q=__webpack_nonce__&type=Further readings:
The text was updated successfully, but these errors were encountered: