Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSP unsafe-inline required to use? #616

Closed
lol768 opened this issue Feb 12, 2018 · 22 comments
Closed

CSP unsafe-inline required to use? #616

lol768 opened this issue Feb 12, 2018 · 22 comments
Assignees

Comments

@lol768
Copy link

lol768 commented Feb 12, 2018

Version

4.1.3

Browser and OS info

Firefox 59.0b8

Steps to reproduce

  • Read README
  • Attempt to use Vue dev tools on site with strict CSP headers
  • Check console for errors:

Content Security Policy: The page’s settings blocked the loading of a resource at self (“script-src”). Source: ;(function(e){let t={};if(e.hasOwnProper....
Page:1

Content Security Policy: The page’s settings blocked the loading of a resource at self (“script-src”). Source: ;(function(e){setTimeout(()=>{const n=do....
Page:1

Content Security Policy: The page’s settings blocked the loading of a resource at self (“script-src”). Source: ;(function(e){let n=null,t=0;const o={no....
Page:1

  • Re-read README.md hoping that requirement to inject scripts in this way is documented somewhere
  • Relax CSP headers to allow unsafe-inline
  • Vue devtools start working

What is expected?

  • Dev tools should operate without having to compromise on site security by allowing inline scripts
  • If this isn't technically possible, this incompatibility should be documented clearly in the README

What is actually happening?

  • Dev tools cannot detect running Vue instance
@Akryum
Copy link
Member

Akryum commented Feb 12, 2018

The devtools can't communicate with the webpage without injecting a script.

@lol768
Copy link
Author

lol768 commented Feb 14, 2018

Does it have to be inline? Can you reference a moz-extension script, or one that's externally hosted?

@chearon
Copy link
Contributor

chearon commented Feb 15, 2018

There's at least one extension developer who's gotten around CSP. This was a hard error to figure out for me, and disabling CSP locally isn't really ideal either. I haven't looked at how the extension communicates with Vue yet, but there might be a way...

@chearon
Copy link
Contributor

chearon commented Feb 16, 2018

Been playing around a bit with this and I've found a few ways to get the dev tools working with CSP enabled. The first two solutions require changes to vue-devtools:

  1. In hook.js and detector.js where the <script> elements are created, if it did a setAttribute('nonce', 'vue') then for dev mode people could add 'nonce-vue' to script-src. This would leave CSP on for everything else so you can still catch stray script tags before going on production huh, actually I think this issue is Firefox-only
  2. Firefox actually lets you evaluate stuff on the main window using window.eval(), so for that browser you could skip the createElement('script') entirely.
  3. If neither of these got merged or for those who need a solution now, you can just add the intializing code into to your development build. The function in hook.js goes before require('vue'), then add window.postMessage({devtoolsEnabled: true, vueDetected: true}, '*') right after. I might release an NPM module to make it easier.

Would a PR for 1 and 2 be accepted?

chearon added a commit to chearon/vue-devtools that referenced this issue Feb 16, 2018
chearon added a commit to chearon/vue-devtools that referenced this issue Feb 16, 2018
chearon added a commit to chearon/vue-devtools that referenced this issue Feb 16, 2018
chearon added a commit to chearon/vue-devtools that referenced this issue Feb 16, 2018
@lol768
Copy link
Author

lol768 commented Feb 20, 2018

Hey @chearon!

Appreciate you taking the time to look into this.

There's at least one extension developer who's gotten around CSP

Admittedly this is a creative solution, but I wouldn't say it's the nicest fix I've ever seen 😉

if it did a setAttribute('nonce', 'vue') then for dev mode people could add 'nonce-vue' to script-src. This would leave CSP on for everything else so you can still catch stray script tags before going on production

This isn't a bad approach. My only worry would be people leaving this on in production (and then it becomes a neat way for you to bypass CSP for your XSS payload!) -let's be honest, at least one person would probably do this so it feels too much like giving developers a shotgun to blow their own feet off with.

Firefox actually lets you evaluate stuff on the main window using window.eval(), so for that browser you could skip the createElement('script') entirely.

Interesting, and it seems like in Chrome the extensions aren't impacted by CSP either (which is in-line with how I'd expect extensions to be treated by the browser). This could be a nice workaround for Firefox.

If neither of these got merged or for those who need a solution now, you can just add the intializing code into to your development build. The function in hook.js goes before require('vue'), then add window.postMessage({devtoolsEnabled: true, vueDetected: true}, '*') right after. I might release an NPM module to make it easier.

Honestly, I don't understand why this wasn't the approach taken from the beginning: two separate builds, one dev build with the dev tools initialization code in and one prod build without it. Am I missing something obvious which would have prevented this from working? Why is injecting scripts into the page preferable? I'm pretty sure React took the same approach and I really don't understand why.

I can't see that this would cause problems if the dev tools weren't there, it'd just be a message sent into the aether.

@chearon
Copy link
Contributor

chearon commented Feb 20, 2018

I think the post I linked to was solving something a little different actually.

Interesting, and it seems like in Chrome the extensions aren't impacted by CSP either

Yep. So this issue is entirely a Firefox compatibility thing (see #621 which fixes it, I've been using it).

Honestly, I don't understand why this wasn't the approach taken from the beginning...Why is injecting scripts into the page preferable

I dunno, maybe a Vue team member can answer that. It does seem cleaner to have the initialize code inside a dev build; it wouldn't have to detect Vue by checking every element after X seconds. All browsers do support content scripts behind CSP in one way or another though.

@Akryum
Copy link
Member

Akryum commented Feb 20, 2018

I think this is to support Vue.config.devtools = true. And also not to increase the size of the library in production.

@michalsnik
Copy link
Member

michalsnik commented Mar 11, 2018

Hey, as I wrote in #621 I don't think we can go around unsafe-inline with eval, because it would violate unsafe-eval option in CSP directive. The nonce that isn't automatically regenerated on each request totally introduces security vulnerability too.

I see two possible solutions:

@michalsnik michalsnik self-assigned this Mar 11, 2018
@lol768
Copy link
Author

lol768 commented Mar 11, 2018

And also not to increase the size of the library in production.

Why can't there be two separate builds, or a separate script we include on the page which contains the hook (which then won't trip CSP)?

@michalsnik
Copy link
Member

michalsnik commented Mar 11, 2018

So apart from installing plugin you would like to attach another script and also make sure whether those versions are compatible? I guess not :D

What might solve your problem is remote @vue/devtools. Have you tried it already?
Once you'll install it, you have to import script from npm package that includes hook and all necessary stuff to connect to dedicated vue-devtools app. I believe it should solve your CSP issue @lol768

so this is the 3rd solution ☝️

@lol768
Copy link
Author

lol768 commented Mar 11, 2018

I hadn't tried that, @michalsnik - but it's an interesting solution. Presumably I'd only need to add localhost to my script-src and that'd be it on the CSP side?

@chearon
Copy link
Contributor

chearon commented Mar 11, 2018

Over here I mentioned that extensions don't violate CSP and that dev environment headers are kinda risky.

Whitelist specific hash in CSP directives , it's unique for each string, and it's impossible to trick it, as any modification in source code (even white space) will result in different sha calculation. More informations here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src

I also went down this route but if I understand right, we have to update the hash any time you guys make changes to those files right?

What might solve your problem is remote vue/devtools.

I'm glad there's several options, but all of them involve us doing something or changing the application in a way to make the extension work. That's kind of a bummer considering Chrome users don't have to do anything :(

Akryum pushed a commit that referenced this issue Jul 26, 2018
* Don't break when CSP is on in Firefox (#616)

* fix: eslint disable comments

* feat: $isFirefox
@jbosse
Copy link
Contributor

jbosse commented Nov 8, 2018

I am actually getting a CSP error in Chrome as well, not for the script but for the inline styles needed for the hilighting components in the DOM.

Chrome will also not allow the inline style even if the has is added to style-src header. 😢

backend.js:1 Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'"

I don't think this is easily addressed until CSP 3.0 establishes a mechanism for allowing it and the best solution I can see is to add a setting to the extension that would simply disable the feature so my console log isn't getting spammed with CSP errors.

@TheCycoONE
Copy link

In firefox I'm now getting: Content Security Policy: The page’s settings blocked the loading of a resource at eval (“script-src”). and the extension still isn't working when CSP is enabled (without unsafe-*)

@TheCycoONE
Copy link

TheCycoONE commented Jan 14, 2019

https://bugzilla.mozilla.org/show_bug.cgi?id=1267027 is the relevant upstream bug. I've read it, but I'm not sure if there is content that is useful, or specifically what changed in Firefox 58.

In particular they point to the 'contentScripts' API as a workaround.

@chearon
Copy link
Contributor

chearon commented Jan 14, 2019

You're right, when I take off unsafe-eval the extension no longer works. #621 only fixes unsafe-inline.

Too bad for Firefox. It's pretty clear they're doing it wrong. Someone on that bugzilla issue said the react/redux devtools have the same problem, which is probably just causing more devs to switch to Chrome.

contentScripts looks promising though. I'll support your PR! Or open one if I find the time.

@cawoodm
Copy link

cawoodm commented Apr 3, 2019

Is it correct that Vue doesn't work with CSPs which don't allow unsafe-eval?
https://codepen.io/cawoodm/pen/eopwGP

That's a pity for Electron developers where we are warned about NOT allowing unsafe-eval.
image

@Riplar
Copy link

Riplar commented Jul 8, 2019

@cawoodm I have the exact same problem. Did you find a solution?

@jbosse
Copy link
Contributor

jbosse commented Jul 8, 2019 via email

@Riplar
Copy link

Riplar commented Jul 8, 2019

I just found a working solution:

new Vue({
  el: '#app',
  store,
  router,
  i18n,
  render: function(createElement) {
    return createElement(App);
  },
  components: {
    App
  },

https://www.codementor.io/vuejsdevelopers/why-you-should-avoid-vue-js-dom-templates-c4chvgjlh

@rnicholus
Copy link

It seems this is still an issue, preventing any apps with reasonable CSPs from using vue-devtools in Firefox. Has anyone found a workaround, or have an idea about how to update this add-on to fix that?

@kir0ul
Copy link

kir0ul commented Mar 27, 2021

I have the same problem as in thelounge/thelounge#3897, I get Vue.js not detected as well as a long list of messages like the following with Firefox 87.0 and Vue.js devtools 5.3.4:

Content Security Policy: The page’s settings blocked the loading of a resource at http://localhost:8098/socket.io/?EIO=3&transport=polling&t=NXo1bfS (“connect-src”).

@vuejs vuejs locked and limited conversation to collaborators Feb 10, 2022
@Akryum Akryum converted this issue into discussion #1701 Feb 10, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants