styled-components / styled-components

Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅
https://styled-components.com
MIT License
40.12k stars 2.48k forks source link

Add Support for Easily Configuring a Nonce. #4258

Open ekramer-taulia opened 3 months ago

ekramer-taulia commented 3 months ago

With the widespread adoption of the Content Security Policy header and the known security risks associated with using unsafe-inline, Styled Components should provide an easier way to apply a nonce to its inline styles so unsafe-inline is not required.

I have examined some of the suggested workarounds, but none of them are straight forward or applicable to my use case, and I think a simple way to configure a nonce at runtime with a value provided from any server would provide much better nonce support in Styled Components.

Use Case

In my case I am not using Styled Components directly in my app, but it is being used by another library that I am using (Looker), so the solutions suggested here are not easily implemented.

Suggested Solution

I suggest a way to globally configure the nonce that Styled Components uses for all style tags appended to the document. In my use case a unique nonce value from the server is assigned to a variable on the window object on every request. When the React application initializes, that nonce variable could be assigned to a nonce configuration object that Styled Components uses for all subsequent style tags.

I have looked at the nonce support using the __webpack_nonce__ variable, but this has some problems

I think it would be relatively easy to add a nonce API that builds off of this util, but allows the nonce to defined at runtime, something like this:

// index.js

import nonceConfig from 'styled-components'

// ...

nonceConfig.setNonce(window.myNonce)
// nonce.ts

+ import nonceConfig from 'styleComponents'

declare let __webpack_nonce__: string;

export default function getNonce() {
  + const configuredNonce = nonceConfig.getNonce()
  + if (configuredNonce) {
  +   return configuredNonce
  + }
  return typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null;
}

I would be happy to make a PR to implement this if the maintainers agree.

Thank for you consideration

Varnius commented 2 months ago

Voting this up! The proposed solution would work, though our use case is a bit different - it's a library that our clients add to their page in order to render a UI widget. The library uses styled-components and some of the clients want to add a nonce value to the style block in order to apply proper CSP. We currently use a patched version of styled-components but it's a hassle when we want to update the version in use.

barbalex commented 2 months ago

I just ran into this building an electron app. Electron wants devs to define a csp (https://www.electronjs.org/docs/latest/tutorial/security#7-define-a-content-security-policy).

Which failed in my case because the app is using styled-components and thus this error occurs:

Refused to apply inline style because it violates the following Content Security Policy directive: "default-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='), or a nonce ('nonce-...') is required to enable inline execution. Note also that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.

index-BHPOJIUy.js:40 Error: An error occurred. See https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/utils/errors.md#17 for more information.
    at Eh (index-BHPOJIUy.js:68:4015)
    at index-BHPOJIUy.js:68:6579
    at new e (index-BHPOJIUy.js:68:6586)
    at index-BHPOJIUy.js:68:8976
    at e.getTag (index-BHPOJIUy.js:68:8996)
    at e.insertRules (index-BHPOJIUy.js:68:9330)
    at e.generateAndInjectStyles (index-BHPOJIUy.js:68:13004)
    at index-BHPOJIUy.js:68:14927
    at index-BHPOJIUy.js:68:14985
    at b (index-BHPOJIUy.js:68:15128)