nuxt-modules / color-mode

Dark and Light mode with auto detection made easy with Nuxt 🌗
https://color-mode.nuxtjs.org
MIT License
1.07k stars 98 forks source link

feat: link script in head for CSP 'self' compliance in v3 #266

Closed dargmuesli closed 2 months ago

dargmuesli commented 3 months ago

Is your feature request related to a problem? Please describe.

I'd like to not have any inline scripts to enforce a strict Content Security Policy.

Describe the solution you'd like

The color-mode script should not be inlined as done here https://github.com/nuxt-modules/color-mode/blob/65c90d46372867e1d28a3bbd4ee975c05932f41e/src/runtime/nitro-plugin.ts#L7 but instead be an external file that is linked.

Describe alternatives you've considered

Set script-src: 'unsafe-inline' (which is unsafe)

Additional context

This was previously done for Nuxt 2 here: https://github.com/nuxt-modules/color-mode/blob/65c90d46372867e1d28a3bbd4ee975c05932f41e/src/runtime/nitro-plugin.ts#L7

gregmsanderson commented 2 months ago

Ah perhaps this is the issue I'm having too.

I noticed I was getting "Refused to execute inline script because it violates the following Content Security Policy directive" errors in the console. After commenting out the @nuxtjs/color-mode module those went away.

I tried keeping the color module and commented out nuxt-security. Again the error went away (naturally, as then there was no CSP to check!).

So it seems that using nuxt-security with its default options (well, slightly modified to get dev tools working) causes the color mode to not work.

Gerbuuun commented 2 months ago

After my investigation, this seems to be the culprit of the problems I'm having. (described in #228 and #267) In development it seems to work just fine. But after prerendering pages, nuxt-security applies nonce values on everything. Because there is a nonce value on the color-mode script even with unsafe-inline it won't execute. This is only the case with prerendered pages. SSR works just fine.

Gerbuuun commented 2 months ago

Ok I went deep into @nuxtjs/color-mode and nuxt-security and have found the bug.

It turns out that the newline breaks the detection from nuxt-security and as such the script does not receive a hash and the CSP will block it.

Now I don't know which of the two need to be fixed (in my opinion probably both right?) The minified script does not need a newline at the end nuxt-security inline script detection should not break when a newline is inside the script

edit: @Baroshem what do you think about this?

Baroshem commented 2 months ago

The Nuxt Security part was fixed. Thanks for reporting that :)