Skip to content
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

Tampermonkey userscript doesn't work in chrome because of CSP #593

Closed
Loceka opened this issue Aug 30, 2018 · 4 comments
Closed

Tampermonkey userscript doesn't work in chrome because of CSP #593

Loceka opened this issue Aug 30, 2018 · 4 comments

Comments

@Loceka
Copy link

Loceka commented Aug 30, 2018

Hello,

I've run into an issue with a website declaring a Content Security Policy in a tag :

<meta http-equiv="Content-Security-Policy" content="default-src 'self' *.<site url>; img-src 'self' *.<site url> data:;connect-src ws: wss: 'self' *.<site url>;">

Even the simplest scripts such as (this is the whole script, so only the meta-data is enough to raise an error):

// ==UserScript==
// @name          test
// @namespace     test
// @include       <url>
// @grant         none
// ==/UserScript==

fails with the error EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self' *.<site url>".

It is even worse when I set // @grant GM_getValue (or anything but "none") : instead of raising an error 70% of the time, it raises an error 95% of the time.

This is what I used for the tests :

  • Chromium: 67.0.3396.99
  • TM: 4.7
  • OS: Windows and Linux (manjaro)

In addition, the same script on the same website but with Firefox/Tampermonkey runs well.
So the problem is chrome/chromium related.

I've checked the Tampermonkey security parameters and in both browsers they are set to the default :
Add Tampermonkey to the website content security policy (CSP) if any : yes (it may not be the exact english version since I have a translation)

@derjanb
Copy link
Member

derjanb commented Aug 31, 2018

Unfortunately Tampermonkey can not change inline CSP meta tags. There is a request to allow extension to modify the request body, but this is not implemented yet (at least in Chrome)

You are right that Tampermonkey can trigger a "EvalError: Refused to evaluate a string as JavaScript" warning at such CSP secured pages, but then a workaround is used to inject the scripts. This means scripts should at least start even if some functionality is broken by CSP.

And this seems to work here as expected. Just install this script and visit http://test.tampermonkey.net/csp_header.php?scp=default-src+%27self%27+*.tampermonkey.net%3B+img-src+%27self%27+*.tampermonkey.net+data%3A%3Bconnect-src+ws%3A+wss%3A+%27self%27+*.tampermonkey.net%3B&meta=true

// ==UserScript==
// @name          Meta Tag CSP
// @namespace     test
// @include       http://test.tampermonkey.net/csp_header.php?scp=default-src+%27self%27+*.tampermonkey.net%3B+img-src+%27self%27+*.tampermonkey.net+data%3A%3Bconnect-src+ws%3A+wss%3A+%27self%27+*.tampermonkey.net%3B&meta=true
// @grant         GM_getValue
// @grant         GM_setValue
// ==/UserScript==

console.log('running', GM_getValue('ts'));
GM_setValue('ts', Date.now());

eval('console.log("foo");');

As you can see, "running" and a timestamp is logged, but eval fails due to CSP.
So can you please describe your problem more in detail? Thanks.

Note: you can also play with "Inject Mode" "Instant" and @run-at "document-start" to make the eval command succeed.

@Loceka
Copy link
Author

Loceka commented Sep 1, 2018

The first script doesn't quite work as it sometimes allows setting/getting the value and sometimes doesn't same error as in the first post.

But setting the @run-at to "document-start" does the trick, as long as the script doesn't try to perform an eval or to create an inline script (since it is forbidden by CSP).
I've tried (and succeeded in) removing the tab declaring the CSP, or changing its "content" attribute value but it seems that chrome doesn't care about that at all and sticks with the value that was first loaded.

Still, the script can be executed if runned at document-start.

Thanks for the tip!

@Loceka Loceka closed this as completed Sep 1, 2018
@sebastian684
Copy link

Hey @Loceka,
thanks for the update and feedback that you have get it to work!
Can you maybe please descripe how you get this working because I am working with Google Tag Manager and Google Optimize which I am loading via Tampermonkey. right now, i cant use this on a special website because its being blocked by CSP.
I would like to override this but I am not really sure how to use the above 2 scripts.
Thanks,
Sebastian

@raszpl
Copy link

raszpl commented Dec 6, 2020

@derjanb did this just stop working?

VM109:62 Syntax error @ "CSP test"!
EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self' *.tampermonkey.net".

VM109:62 Syntax error @ "Meta Tag CSP"!
EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self' *.tampermonkey.net".

 Chrome/87.0.4280.88
 v4.12.6122
 W10

uBO injected scripts (scriptlets) still run fine EDIT: I read later its because they use extension context, never mind

I had this convoluted and naive idea for a temporary quick workaround involving Injecting in instant mode and window.stop(),

window.stop()
GM_xmlhttpRequest the page that was just stopped
document.body = document.createElement('body')
manually fill in head and body tags.
emulate DOMContentLoaded, load events

but I cant create head (document.head = document.createElement('head') nopes)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants