vuejs / vue-class-component

ES / TypeScript decorator for class-style Vue components.
MIT License
5.81k stars 429 forks source link

unsafe-eval CSP issue with v8.0.0-rc.1 #509

Closed websmurf closed 3 years ago

websmurf commented 3 years ago

I've converted an older Vue 2 + Vue 2 CLI plugin to Vue3, Vite and vue-class-component and since this upgrade I'm running into a CSP issue which seems to come from vue-class-component 8 RC1:

image

If you open the console, you can see the error here: https://my.bandhosting.nl

Still looking into where the piece of code that's causing this originates from, so will update this issue if I can find it.

websmurf commented 3 years ago

The source of the error is this part new Function in the compiled vue-class-component source:

{try{self[t]=new Function("u","return import(u)")}catch(n)
flyfishzy commented 3 years ago

Will you provide a reproduction github repo?

websmurf commented 3 years ago

Any repository using vue-class-component has this issue, but sure, will provide a repo later (on holiday right now)

Verzonden via m'n iPhone

Op 18 feb. 2021 om 07:15 heeft Joe Zhang notifications@github.com het volgende geschreven:

 Will you provide a reproduction github repo?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

websmurf commented 3 years ago

I've added a CSP record here: https://github.com/websmurf/vue-router-async-test

You can check with yarn build && yarn preview. The error is a bit different though than what I'm getting live. It's the same piece of code though:

let d;!function(e=".",t="__import__"){try{self[t]=new Function("u","return import(u)")}catch(r){const n=new URL(e,location),o=e=>{URL.revokeObjectURL(e.src),e.remove()};self[t]=e=>new Promise(((r,a)=>{const i=new URL(e,n);if(self[t].moduleMap[i])return r(self[t].moduleMap[i]);const c=new Blob([`import * as m from '${i}';`,`${t}.moduleMap['${i}']=m;`],{type:"text/javascript"}),u=Object.assign(document.createElement("script"),{type:"module",src:URL.createObjectURL(c),onerror(){a(new Error(`Failed to import: ${e}`)),o(u)},onload(){r(self[t].moduleMap[i]),o(u)}});document.head.appendChild(u)})),self[t].moduleMap={}}}("/assets/");const m={},y=function(e,t){if(!t)return e();if(void 0===d){const e=document.createElement("link").relList;d=e&&e.supports&&e.supports("modulepreload")?"modulepreload":"preload"}return Promise.all(t.map((e=>{if(e in m)return;m[e]=!0;const t=e.endsWith(".css"),r=t?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${e}"]${r}`))return;const n=document.createElement("link");return n.rel=t?"stylesheet":d,t||(n.as="script",n.crossOrigin=""),n.href=e,document.head.appendChild(n),t?new Promise(((e,t)=>{n.addEventListener("load",e),n.addEventListener("error",t)})):void 0}))).then((()=>e()))};

But, since the error only occurs on the Async loaded pages, my feeling is that this is caused to the async component loading rather then anything else.

ygj6 commented 3 years ago

It's not a vue-class-component issue. The async import was compiled to a import-polyfill. As a result, you need to change the Content Security Policy to: <meta http-equiv="Content-Security-Policy" content="script-src 'self' blob:">

The reason is that:

This polyfill uses new Function() to feature detect dynamic import() support, and that detect will always fail if your Content Security Policy (CSP) does not allow 'unsafe-eval' (which most do not). This is generally fine, however, because the polyfill fallback will be used instead. Just be aware that such CSP policies will prevent the browser from using its native dynamic import(), even when supported. In addition, this polyfill uses Blob URLs to load modules dynamically, and in order for this to work you must configure your Content Security Policy to allow Blob in your script-src settings. https://github.com/GoogleChromeLabs/dynamic-import-polyfill

websmurf commented 3 years ago

Hmm, but that tactic would mean that a CSP violation (and thus a CSP report) will be generate for every pageload of the html page of a Vue application.

That's quite unfortunate; since a lot of CSP reporting tools charge you based on the amount of CSP reports that your receive. But, since that's not related to Vue class component, I'll go and complain in the correct place 🙂

websmurf commented 3 years ago

For anyone who ends up here

Hmm, but that tactic would mean that a CSP violation (and thus a CSP report) will be generate for every pageload of the html page of a Vue application.

This conclusion is incorrect; adjusting the policy to include blob: gets rid of this error without a CSP violation