24

Is there a way to make Vue.js to work with CSP properly?

When I run my spa application (resulting from npm run generate with Nuxt.js), I will get several warnings such as these:

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 'strict-dynamic' 'nonce-124lk5fjOc4jn7qqLYEsG2jEvxYuqu8J' 'unsafe-inline' https:". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

Knowing CSP, there are two correct ways of fixing this:

  1. Using nonces, where Vue.js would have to sign all the generated scripts and styles with a nonce attribute. But I don't think this would solve anything, since it appears some CSS is added inline.

  2. Using hashes, which is actually the preferred way of doing it, since the hash secures exactly what we want the client to execute on the browser.

However, in order to use hashes, Vue.js/Webpack must be able to calculate the hash for all its scripts and styles, and:

  • for each compilation, tell them to the developer that will then add these hashes to a NGINX configuration file,

or,

  • be able to generate meta tags containing the hashes, making this process 100% transparent to the developer, who doesn't need to configure anything else to guarantee a good CSP protection.

Does Vue.js support this in any way? Is there anyone in the world who was able to make CSP working with Vue.js without any 'unsafe-inline'?

PedroD
  • 5,670
  • 12
  • 46
  • 84

3 Answers3

8

According to the Vue.js docs, the runtime build is fully CSP-compliant.

Nuxt is supporting a csp config to create hashes via webpack sent as header on dynamic SSR mode and meta elements otherwise (see https://github.com/nuxt/nuxt.js/pull/5354)

tony19
  • 125,647
  • 18
  • 229
  • 307
manniL
  • 7,157
  • 7
  • 46
  • 72
  • Awesome! How the hell did I search for this week after week and google never showed me this part of Nuxt documentation? I am gonna try to test this solution and let you know. Still, it seems too good to be true :P – PedroD Oct 16 '19 at 12:13
  • Nuxt's CSP features seem to work only with SSR... Is there a way to make it work with static (I generate my spa with `npm run generate`)? – PedroD Oct 16 '19 at 15:27
  • Yes. please check out the last GH link I've posted – manniL Oct 18 '19 at 11:22
  • So, in sum I should add the `addMeta` to `true`, and use any Nuxt version above that commit (2.6.0). I am using Nuxt v2.10.1, and I have the following in my nuxt.config file (https://pastebin.com/hV7mWyfQ), however nothing happens, no hashes are generated and no meta tags with CSP policies... I am using `npm run generate` to create the static distribution into the default `dist` folder. I am so at lost, I must be missing something really dumb. – PedroD Oct 18 '19 at 13:19
  • I've opened a bug in github, since I was not able to produce any results while trying to follow any steps, I added a sample project to reproduce the issue as well. https://cmty.app/nuxt/nuxt.js/issues/c9929 – PedroD Oct 19 '19 at 09:11
  • @PedroD looks like we ran into a similar problem - did you find a solution without having to move to SSR? – Matt H Dec 17 '19 at 19:31
  • 2
    @MattH no.. :( I think this is a limitation of Nuxt. Even on SSR things do not work well. Nuxt is not capable of automatically calculate all hashes for the inline scripts and styles, so you end up using unsafe-inline anyway... It sucks. Major security flaw, by design. – PedroD Dec 17 '19 at 22:28
  • oh yikes! Thank you so much, that saved me time from working around a SSR/expressjs solution - I might have to see if migrating out of nuxt and back to vue cli provides us with what we need then :( – Matt H Dec 18 '19 at 04:57
  • 2
    To me it seems this is only working for `scripts`, but `styles` still requires `unsafe-inline`. Am I wrong? – some-user Dec 07 '20 at 12:04
  • @some-user indeed you are correct – PedroD Oct 17 '21 at 10:10
4

you could use the --no-unsafe-inline option in your npm run build script

https://cli.vuejs.org/guide/cli-service.html#vue-cli-service-build

Charles Okwuagwu
  • 10,538
  • 16
  • 87
  • 157
0

Not sure if this is better as a comment or not but it kinda works so putting it here for now.

Our deployment strategy might be a bit different, but essentially we trigger a lambda to update the cloudfront csp with our CI/CD.

We noted that the inline scripting was static despite different app versions/bumps. Our current workaround is:

  1. Deploy on a dev server - get the sha256 hash from the chrome dev tools (you could probably calculate it yourself to avoid deploying)
  2. Updated our terraform cloudfront lambda CSP with the hash
  3. On the new deploy the hash matches and we don't need unsafe-inline

Some big limitations re: if nuxt changes the inline script on new versions we'll have to manually update our hash in the CSP. Also, depending on your styling framework there may be a number of inline-styles which aren't captured here.

Matt H
  • 710
  • 1
  • 7
  • 10