Closed Bug 1645614 Opened 6 months ago Closed 5 months ago

CSP errors when "Using eval in content scripts"

Categories

(WebExtensions :: General, defect)

77 Branch
defect

Tracking

(Not tracked)

RESOLVED DUPLICATE of bug 1591983

People

(Reporter: jan, Unassigned)

Details

Attachments

(1 file)

2.55 KB, application/zip
Details
Attached file csp-test.zip

User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/83.0.4103.61 Chrome/83.0.4103.61 Safari/537.36

Steps to reproduce:

Hi, Tampermonkey dev here. I start to sorely miss a Firefox feature more and more. Please install the attached example extension in Chrome (extracted zip via "Load unpacked") and in Firefox (via Load Temporary Add-on).

Taken from https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Using_eval_in_content_scripts:

In Firefox
If you call eval(), it runs code in the context of the content script.

If you call window.eval(), it runs code in the context of the page.

OK, then let's test this: please visit the following pages with the JavaScript console open.

Actual results:

Chrome <<<

http://test.tampermonkey.net/csp/no_csp.php

> content script

> window.eval'ed page script

> injected page script

> injected and evaluated page script

> injected and inejected page script

http://test.tampermonkey.net/csp/strict_csp.php

> content script

> window.eval'ed page script

> injected page script

VM80:1 Uncaught 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 'none'".

at <anonymous>:1:1

(anonymous) @ VM80:1

> injected and inejected page script

Firefox <<<

http://test.tampermonkey.net/csp/no_csp.php

> content script content.js:1:9

> window.eval'ed page script eval:1:9

> injected page script no_csp.php:1:9

> injected and evaluated page script no_csp.php line 1 > eval:1:9

> injected and inejected page script

http://test.tampermonkey.net/csp/strict_csp.php

> content script content.js:1:9

Content Security Policy: The page’s settings blocked the loading of a resource at eval (“default-src”). 2
Content Security Policy: The page’s settings blocked the loading of a resource at inline (“default-src”). common.js:2:319
Content Security Policy: The page’s settings blocked the loading of a resource at http://test.tampermonkey.net/favicon.ico (“default-src”).

Expected results:

As you can see, Firefox extensions are not allowed to inject or evaluate scripts into CSP secured pages, while this works fine in Chrome.

This behavior forces Tampermonkey and maybe other extensions to alter (relax) the page's CSP which now (since Firefox 77) does not work anymore.
At least some of my users now disable CSP globally, which can't be the right solution for this issue, right?
That's why Tampermonkey now has an option to remove the CSP only at pages where scripts are supposed to run at and this is better than to disable CSP globally, but again: this can't be the right solution for this issue.

Also CSP modification works very bad with pages cached by service workers. Some Tampermonkey users therefore disable "dom.caches.enabled" and are now afraid that this options might be removed -> https://bugzilla.mozilla.org/show_bug.cgi?id=1643405

That's why please allow content scripts to inject inline script tags or window.eval code as described at the documentation and if possible exempt them from CSP at least for the current execution cycle. This way pages can have their CSP and extensions still can run code inside the page context.

I'll explain why I'm not using the browser.userScripts API at the next post. However, this feature should work independent from this API.

Note: this issue belongs to this meta issue -> https://bugzilla.mozilla.org/show_bug.cgi?id=1267027
I hope it's not a simple duplicate, because 1267027 is there since 4 years now.

Thanks.

OK, so why doesn't Tampermonkey use the browser.userScripts API?

Tampermonkey executes scripts at the page context, this is the way it is done at 10 million Chrome users and also million of MS Edge, Opera, Brave, Vivaldi and Safari users and 450k Firefox user for more than 10 years now (OK, only 4 years for FF users. ;-)).
This is the first point, I try to share as much code between also browser as possible. This avoids bugs and reduces my test amount. And I try to avoid backwards incompatible changes.

Second the userScripts API only takes globs/match pattern while Tampermonkey userscripts also can use regular expressions. This means I have to wrap the API and inject scripts into every page and check the regular expression once the injected code starts.

Third, as far as I know, the userScripts scripts do have their own execution context and not the page context. Of course they can access the page's window, but they need to use wrappedJSObject and cloneInto and such. This change will break thousands of userscripts unless I find an option to mitigate this problem.

Bugbug thinks this bug should belong to this component, but please revert this change in case of error.

Component: Untriaged → DOM: Security
Product: Firefox → Core
Component: DOM: Security → General
Product: Core → WebExtensions

The inability to bypass the page's CSP with window.eval is a duplicate of bug 1591983. Without discounting the validity and appreciation for your detailed bug report, I'm still going to mark it as a duplicate of bug 1591983 because the engineering work will be the same in both cases.

Independently of that, the userScripts API also has gaps that can be filled.

This is the first point, I try to share as much code between also browser as possible. This avoids bugs and reduces my test amount. And I try to avoid backwards incompatible changes.

Do you know whether your add-on is compatible with Chrome's intended CSP changes in manifest v3? By the looks of it, your add-on will be broken if Chrome proceeds with enforcing a strict CSP for content scripts per https://developer.chrome.com/extensions/migrating_to_manifest_v3#csp_changes

Second the userScripts API only takes globs/match pattern while Tampermonkey userscripts also can use regular expressions. This means I have to wrap the API and inject scripts into every page and check the regular expression once the injected code starts.

--> bug 1445909

Third, as far as I know, the userScripts scripts do have their own execution context and not the page context. Of course they can access the page's window, but they need to use wrappedJSObject and cloneInto and such. This change will break thousands of userscripts unless I find an option to mitigate this problem.

Breaking thousands of user scripts is not good. --> bug 1437867

Status: UNCONFIRMED → RESOLVED
Closed: 5 months ago
Resolution: --- → DUPLICATE
Duplicate of bug: 1591983

Do you know whether your add-on is compatible with Chrome's intended CSP changes in manifest v3? By the looks of it, your add-on will be broken if Chrome proceeds with enforcing a strict CSP for content scripts [...]

I spoke to the extension team and the plan back then was to add an option that allows Tampermonkey to continue working.
How much the option will be "hidden" was not yet clear.

https://groups.google.com/a/chromium.org/d/msg/chromium-extensions/MPcq-feSK9c/mxsQG1BNBwAJ

You need to log in before you can comment on or make changes to this bug.