Content scripts window.eval should not be subjected to CSP restrictions
Categories
(WebExtensions :: General, enhancement, P3)
Tracking
(Not tracked)
People
(Reporter: tartpvule_ggi, Unassigned)
References
(Blocks 1 open bug)
Details
- Make a WebExtension with content script doing
window.eval("(function() { alert('Hello World') })()")
- Navigate to a page with CSP directives set to block eval e.g.
www.github.com
Current Result:
No alert box appears.
In browser console: EvalError: call to eval() blocked by CSP
Suggestion:
window.eval
calls from a WebExtension addon should not be subjected to the content page's CSP directives.
Related but not quite the same:
Bug 1267027 about content inserted into the page DOM
Bug 1580514 about eval-ing from devtools
Comment 1•5 years ago
|
||
Currently all forms of inline code are blocked. Not just window.eval
, but also inline <script>
elements.
In Chrome, inline scripts are allowed, regardless of CSP. window.eval
executes in the context of the content script instead of the web page, so the behavior there is not as relevant.
Depending on your constraints, there may be alternatives that you can use:
-
If you just want to read or write properties from the page's scope, use
.wrappedJSObject
- https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts#Accessing_page_script_objects_from_content_scripts -
If you want to run code in the context of the page, but it is fine if it is not immediately executed, then you could use a
<script>
element with itssrc
set to amoz-extension:
-URL of your extension. To prevent UUID leakage (bug 1372288), wrap it inside a closed shadow element though. Here is an example: https://github.com/Rob--W/dont-slack-redir/blob/e5646287671cb202193d51c03b770c3b40eb3bd2/contentscript.js
If you really need to immediately run arbitrary code in the context of the page in the presence of a strict CSP, then you're out of luck (for now?).
I guess I'm out of luck. :( :(
I have a private (will never be released) extension that instruments and extensively interferes with a hostile page's script.
A large part could be done with exportFunction
, but that doesn't cover everything I require, for example
- Creating a constructor such that
(new testFn()) instanceof testFn === true
requires something monstrous like
var _prototype = (new window.Object()).wrappedJSObject;
var testFn = exportFunction(function() {
var obj = window.Object.wrappedJSObject.create(testFn.prototype);
return obj;
}, window).wrappedJSObject;
testFn.prototype = _prototype;
window.wrappedJSObject.testFn = testFn;
Detecting the case where it's called as a mixin constructor requires more black magic with XPCNativeWrapper.unwrap
(undocumented).
2. It cannot create other kinds of function that is not plain old classic ones, like arrow functions and member functions, such that toString
spits out the correct kind of code.
3. Function forwarders have a lot of overhead per call compared to a plain function created with a window.eval
.
Maybe exportFunction
could be improved? But that's another issue, I guess.
Comment 3•5 years ago
|
||
Have you looked into the Proxy API? This API is designed for transparently wrapping JavaScript objects and functions to change or inspect their runtime behavior.
Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Thank you for the information about Proxy
.
It works, but 1) it's at least 300x slower, and 2) (new Proxy(()=>{}, {})).toString()
doesn't return a string of an arrow function
I have been avoiding Proxy
s due to the very poor performance. Will use it as a fallback.
Still would love an unrestricted window.eval
.
P.S. I know number 2 is a strange thing to ask for, but well, it's to be as stealthy as possible to hostile code.
Updated•5 years ago
|
Please see https://bugzilla.mozilla.org/show_bug.cgi?id=1645614 (duplicate) for a very detailed report and use cases.
Updated•2 years ago
|
Updated•2 years ago
|
Description
•