Will eval() be permitted in content scripts under Manifest V3?

2,183 views
Skip to first unread message

Hr Gwea

unread,
Dec 16, 2019, 11:14:48 AM12/16/19
to Chromium Extensions
The Manifest V3 migration guide says: If you are using eval() in content scripts, then move all external code into your extension bundle.

Does this mean that it won't be possible to allow the use of  eval() via the CSP content_security_policy.isolated_world ?

If this is the case, then our only option to evaluate JS code in a page would be to inject a <script> element and hope that the page doesn't prevent eval() with its own CSP.

Is this the intention with the new manifest V3?
i.e. to relay the decision (of whether eval() is permitted) to the webpage's author via their own CSP, and the extension developer has to obey?

Andrew

unread,
Dec 16, 2019, 4:52:32 PM12/16/19
to Hr Gwea, Chromium Extensions
You should probably try to re-work your code so yo're not using eval().
Eval() is potentially dangerous, I'd be very surprised if Google allowed it under any circumstances.



--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/279adf77-aba3-45aa-860c-d588e76235a1%40chromium.org.

Hr Gwea

unread,
Dec 16, 2019, 5:16:56 PM12/16/19
to Chromium Extensions
eval() is for those cases when you need to execute code you don't know in advance. e.g. User Script managers or any extension that provides scripting capabilities.

The discusión about the dangers of eval() are unnecessary here.


On Monday, December 16, 2019 at 6:52:32 PM UTC-3, Andrew wrote:
You should probably try to re-work your code so yo're not using eval().
Eval() is potentially dangerous, I'd be very surprised if Google allowed it under any circumstances.



On Mon, Dec 16, 2019 at 9:16 AM Hr Gwea <hrg...@gmail.com> wrote:
The Manifest V3 migration guide says: If you are using eval() in content scripts, then move all external code into your extension bundle.

Does this mean that it won't be possible to allow the use of  eval() via the CSP content_security_policy.isolated_world ?

If this is the case, then our only option to evaluate JS code in a page would be to inject a <script> element and hope that the page doesn't prevent eval() with its own CSP.

Is this the intention with the new manifest V3?
i.e. to relay the decision (of whether eval() is permitted) to the webpage's author via their own CSP, and the extension developer has to obey?

--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extensions+unsub...@chromium.org.

Hr Gwea

unread,
Dec 19, 2019, 1:33:02 AM12/19/19
to Chromium Extensions
Let's ask the question in a simpler way.
Will this code be possible in a content script after MV3?

function myEval(code){
    let elem
= document.createElement('script') ;
    elem
.textContent = code ;
    document
.head.appendChild(elem) ;
}

myEval
("Arbitrary JS code") ;

This is what the documentation refers to as "DOM injected scripts".

This is different from allowing 'unsafe-eval' inside content_security_policy.isolated_world becase the isolated world context has access to a few chrome API functions whereas the page context does not.

wOxxOm

unread,
Dec 19, 2019, 9:17:32 AM12/19/19
to Chromium Extensions
Running DOM scripts is not related to eval() function or unsafe-eval CSP. It's a standards-complying way to run page scripts, which will be possible in ManifestV3 as you can see in the draft (the feature is listed in "declined changes" which means there will be no change regarding this) and in this comment by the main extensions API developer.

Hr Gwea

unread,
Dec 19, 2019, 11:29:24 AM12/19/19
to Chromium Extensions
Injecting a <script> element with arbitrary code is exactly the same as using eval(), so I would say they are very much related.

What I'm trying to figure out is what is the policy that the extensions team is trying to enforce.

Do they want to prevent arbitrary code execution in general ("remotely hosted code" as they call it)?
Or do they only wan't to prevent arbitrary code execution that has access to chrome APIs?

By the two links you provided, the former is discarded. They don't want to prevent arbitrary code in general.

Which means that user script extensions like Tampermonkey and others will be able to continue to work (which makes me wonder why there are so many news about this saying that user script managers could stop working... nonsense).

So, if we are clear that they only want to forbid arbitrary code with access to chrome APIs, and given the fact that the isolated world context only has access to the chrome.storage API and the messaging functions under chrome.runtime, do they still want to prevent arbitrary code in this context?

An attack vector that could exploit a vulnerability related to eval() in the isolated world can very well exploit a similar vulnerability related to myEval (the function I gave in my last post).

I don't see much of a difference. The few chrome APIs that are accesible from the isolated world context doesn't justify for me to prevent eval() in that context.

wOxxOm

unread,
Dec 19, 2019, 12:02:20 PM12/19/19
to Chromium Extensions
On Thursday, December 19, 2019 at 7:29:24 PM UTC+3, Hr Gwea wrote:
Injecting a <script> element with arbitrary code is exactly the same as using eval(), so I would say they are very much related.
No, technically these are different because DOM scripts run in the page context, not in the isolated world of content scripts, so they can't do the same amount of damage as eval() in a content script.
 
An attack vector that could exploit a vulnerability related to eval() in the isolated world can very well exploit a similar vulnerability related to myEval (the function I gave in my last post).
An attack will have a chance only on extensions that accept data from the page context messages and trust them so it's a different threat level compared to direct eval(). 
I don't see much of a difference. The few chrome APIs that are accesible from the isolated world context doesn't justify for me to prevent eval() in that context.
The difference is that it's much harder to compromise the isolated world directly by running an attack from an untrusted context such as the web page/iframe. Anyway you can relax the default CSP for isolated world in manifest.json, for example: "content_security_policy": { "isolated_world": "......" }


Do they want to prevent arbitrary code execution in general ("remotely hosted code" as they call it)?
Or do they only wan't to prevent arbitrary code execution that has access to chrome APIs?
 
In general.

By the two links you provided, the former is discarded. They don't want to prevent arbitrary code in general.

The second link (the comment) says the ability to run DOM scripts remains, it doesn't change the fact that the actual contents of those DOM scripts must be present in the extension package.
 
Which means that user script extensions like Tampermonkey and others will be able to continue to work (which makes me wonder why there are so many news about this saying that user script managers could stop working... nonsense).
 
The way I read the ManifestV3 draft and all the info posted so far, Tampermonkey and other userscript managers won't be allowed in the web store for sure. I remember this topic was discussed many times here and it was ignored every time by Chromium team, which is quite understandable as they hardly want to get the world-wide notoriety for killing one of the most useful extensions.

Hr Gwea

unread,
Dec 19, 2019, 12:18:49 PM12/19/19
to Chromium Extensions
Ok, so you are saying that we will be able to do this:

let elem = document.createElement('script') ;
elem.src = chrome.runtime.getURL('file.js') ;
document.head.appendChild(elem) ;

But not this:
let elem = document.createElement('script') ;
elem.textContent = 'arbitrary code' ;
document.head.appendChild(elem) ;


Simeon Vincent

unread,
Dec 19, 2019, 12:19:26 PM12/19/19
to Chromium Extensions
I agree with most of wOxxOm's assessments save for "Tampermonkey and other userscript managers won't be allowed in the web store for sure." We want to find a way to let Tampermonkey and similar tools keep working while also disallowing other extensions from executing arbitrary script. 

We're enforcing the remotely hosted code (RHC) restrictions through a combination of platform and policy changes. On the platform side we have the CSP changes that prevent extensions from using eval or similar capabilities in extension context and will consider other chances if necessary. On the policy side we have not-yet-written policy changes that will disallow the use of code that isn't bundled in the extension (AKA RHC). We don't have a final plan on how to allow userscript manager style extensions, but I think we're on the right track. 

Cheers,

Simeon - @dotproto
Extensions Developer Advocate

wOxxOm

unread,
Dec 20, 2019, 4:07:23 AM12/20/19
to Chromium Extensions
Not just 'arbitrary code' (as this can be interpreted as a literal code string which is obviously allowed since it's inside the package) but specifically external code, not present in the extension package.

Hr Gwea

unread,
Dec 21, 2019, 3:03:51 PM12/21/19
to Chromium Extensions
On Thursday, December 19, 2019 at 2:19:26 PM UTC-3, Simeon Vincent wrote:
We want to find a way to let Tampermonkey and similar tools keep working while also disallowing other extensions from executing arbitrary script.


Will you provide a workaround for extensions that do this?
chrome.tabs.insertCSS(tabId, {code:'...Arbitrary CSS...'})

The MV3 migration guide doesn't mention chrome.tabs.insertCSS explicitly, but it does say that CSS code must also be in the extension bundle.
This means extensions like Stylish and Stylus face the same fate as user-script managers.

Simeon Vincent

unread,
Jan 3, 2020, 4:19:09 PM1/3/20
to Chromium Extensions
Not just 'arbitrary code' (as this can be interpreted as a literal code string which is obviously allowed since it's inside the package) but specifically external code, not present in the extension package. - wOxxOm

I don't believe this is accurate; to my knowledge the code must be in a file that is included with the extension. As a practical result developers won't be able to ship Webpack development builds.

Will you provide a workaround for extensions that do [chrome.tabs.insertCSS]? … This means extensions like Stylish and Stylus face the same fate as user-script managers. - Hr

I haven't confirmed this with the engineering/product folks, but my understanding is that whatever solution we implement for Tampermonkey would also apply to style customization extensions like Stylish and Stylus. 

Cheers,

Simeon - @dotproto
Extensions Developer Advocate

wOxxOm

unread,
Jan 3, 2020, 11:04:17 PM1/3/20
to Chromium Extensions


On Saturday, January 4, 2020 at 12:19:09 AM UTC+3, Simeon Vincent wrote:
Not just 'arbitrary code' (as this can be interpreted as a literal code string which is obviously allowed since it's inside the package) but specifically external code, not present in the extension package. - wOxxOm

I don't believe this is accurate; to my knowledge the code must be in a file that is included with the extension. As a practical result developers won't be able to ship Webpack development builds.

A literal code string **is** in the file that is included in the extension so your interpretation doesn't seem correct. But if this is what chromium devs came up with, it doesn't make sense and even contradicts itself.

wOxxOm

unread,
Jan 3, 2020, 11:31:07 PM1/3/20
to Chromium Extensions
Note for those chromium developers who conveniently "forgot" or didn't know the difference between the way Chrome processes DOM scripts: a script with a literal code in textContent is executed synchronously so it's possible to run code at document_start before any page script, however when using src pointing to a file such a script will be enqueued with the other page scripts and would run asynchronously at a random point in the future thus breaking functionality of extensions that extend sites with an API on global `window` object. See https://crbug.com/634381

Another difference is that with textContent it's easy to pass arguments like `(functionBody)(${JSON.stringify(argsArray).slice(1,-1)})` without the need to establish messaging. It is extremely important when you need to pass a random id/token that will be used for subsequent communication like e.g. a random event id used for CustomEvent messaging. Without the ability to run literal code via textContent extensions would have to use a predefined event name that can be abused by other scripts running in the page.
Reply all
Reply to author
Forward
0 new messages