Skip to content

Issue setting strict CSP in dev #11862

Closed

Description

@justin-tay

Describe the bug

I am trying to set a strict CSP in dev so that developers don't inadvertently introduce changes that will break the application in production where a strict CSP is applied.

In this case the CSP avoids setting unsafe-inline for style-src

Content-Security-Policy: style-src 'nonce-random' 'self' etc

When running in dev client.ts in Chrome the following errors are seen in console

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'nonce-random' 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-J+3YsBcGEYMOe4DwBHZqef/THcqobccvabWv1wEouI4='), or a nonce ('nonce-...') is required to enable inline execution.
updateStyle | @ | client.ts:377

I will try to submit a PR for this issue. Since unlike webpack there is no convention of where to take the nonce value from like in window.__webpack_nonce__ I will likely get it from a meta tag like marco-prontera/vite-plugin-css-injected-by-js#64

Reproduction

https://github.com/justin-tay/vite-csp-issue.git

Steps to reproduce

Configure vite.config.ts with a strict CSP that disallows unsafe inline for style-src

// https://vitejs.dev/config/
export default defineConfig({
  server: {
    headers: {
      'Content-Security-Policy': `style-src 'nonce-random' 'self'`,
    },
  },
  plugins: [react()],
})

Run npm run dev

System Info

System:
    OS: Windows 10 10.0.22621
    CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
    Memory: 6.91 GB / 15.81 GB
  Binaries:
    Node: 18.13.0 - D:\dev\node\node.EXE
    Yarn: 1.22.19 - D:\dev\node\yarn.CMD
    npm: 8.19.3 - D:\dev\node\npm.CMD
  Browsers:
    Chrome: 109.0.5414.120
    Edge: Spartan (44.22621.1194.0), Chromium (109.0.1518.69)
    Internet Explorer: 11.0.22621.1

Used Package Manager

npm

Logs

No response

Validations

Activity

  1. J5Dev commented on Mar 18, 2023

    @J5Dev

    I think this may be the exact issue I have been experiencing, as described/asked about over on the spatie/laravel-csp package discussion... spatie/laravel-csp#101

    hopefully this will be merged in soon, as this holds us back from fully implementing a good content policy that we don't have to disable when developing locally :/

  2. GalacticHypernova commented on May 31, 2023

    @GalacticHypernova

    Having the same issue here too.
    I feel like changing vite's updateStyle internal behavior would entirely mitigate this conflict, as it can be changed to treat them as files, rather than stringifying them and defaulting to applying inline. It does not even respect styles that are already applied as files. However, if changing the internal process of applying styles on vite's part end isn't reasonable, it should at least treat and respect styles in files accordingly, in stead of breaking them. Nonces would only make it messier the more styles there are.

  3. Kagami commented on Nov 20, 2023

    @Kagami

    Technically you can drop unsafe-inline for style-src in production but IMO it's very dangerous: some part of your code might depend on it and you will break production without noticing. Unless you have a solid QA team...

  4. gitRup-ca commented on Jan 12, 2024

    @gitRup-ca

    So it is still not fixed - a strict CSP using @Vite and Laravel? Has anyone done it? I can not find an answer/example anywhere. So I suggest do not waste your time (3 days now for me) apparently it is a very complex coding issue, and I mean that honestly. I love Laravel, Tailwind CSS, and OMG I love Spatie-CSP and would like to use Livewire. So this is what you do. Do NOT install Laravel JetStream it is too integrated with @Vite now. Create a new Laravel project. Install Fortify (brings in Sanctum as well). Install TailwindCSS. Then install Livewire which uses AlpineJS. Then use route level/group binding with multiple CSP headers as provided by Spatie. And after the guest has authenticated, give them the option to use Livewire reactivity which BREAKS a strict CSP. So a "MANAGER" has Livewire access but a visitor/guest does not. I am not waiting until a framework is built specifically for a strict CSP.

  5. schamberg97 commented on Jan 25, 2024

    @schamberg97

    This is solvable through plugins, albeit it's frightening that Vite devs are unable to offer any solution to this question.

    export default defineConfig(({ mode }) => {
      // something
      const viteClientRegex = /node_modules\/vite\/dist\/client\/client\.mjs$/gi;
    
        // regex'es to add CSP
      // TODO: make one normal regex to handle all three
      const regexScript = /<script(.*?)/gi;
      const replacementScript = `<script nonce="${nonce}"$1`;
    
      const regexStyle = /<style(.*?)/gi;
      const replacementStyle = `<style nonce="${nonce}"$1`;
    
      const regexLink = /<link(.*?)/gi;
      const replacementLink = `<link nonce="${nonce}"$1`;
    
      const nonce = mode === "development" ? "nonce" : "{SERVER-GENERATED-NONCE}";
    
      return {
        plugins: [
          {
            name: "transform-file",
    
            transform(src, id) {
              if (viteClientRegex.test(id)) {
                return {
                  code: src.replace(
                    "style.setAttribute('data-vite-dev-id', id);",
                    `style.setAttribute('data-vite-dev-id', id); style.setAttribute('nonce', '${nonce.toString()}');`
                  ),
                };
              }
            },
          },
          {
            name: "html-inject-nonce-into-script-tag",
            enforce: "post",
            transformIndexHtml(html) {
              return html
                .replace(regexScript, replacementScript)
                .replace(regexStyle, replacementStyle)
                .replace(regexLink, replacementLink);
            },
          },
        ],
      };
    });

    @gitRup-ca @justin-tay FYI. You should mostly be interested in the first plugin

    If someone decides to make a plugin on NPM from this, I'd be grateful if you credit me (have no time ATM to package it all properly)

  6. tnabil commented on Mar 14, 2024

    @tnabil

    @sapphi-red / @patak-dev - quick clarification on this: the mentioned issue solves this using a nonce, which is not suitable for generated / static applications. Are there any plans to implement support for these kinds of applications using hashes?

  7. sapphi-red commented on Mar 14, 2024

    @sapphi-red
    Member

    @tnabil We don't have any plans for that (at least for now). IMO that is easier to do it as a post-process because you'll need to obtain the hashes and set the header anyway. We might consider together with #2377.

  8. locked and limited conversation to collaborators on Mar 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions