Need inputs on migrating from v2 to v3

396 views
Skip to first unread message

Yureshwar Ravuri

unread,
Nov 28, 2021, 11:44:00 PM11/28/21
to Chromium Extensions

We are working on an Open Source Chrome extension: Digital Assistant Client

Product Demo: 

Part 1: https://www.youtube.com/watch?v=Iz2WgKY0fhc 

Part 2: https://www.youtube.com/watch?v=i0_MNfBnYfM

I am planning to move my extension from v2 to v3. I have functionality where i inject script to the head section as text. In v3 they were saying if i add the script it will be considered as remotely hosted code and all the remotely hosted code should be bundled along with the extension package Link. Here is the sample of my code.

var s = document.createElement('script');
s.async = false;
s.onload = function() {
};
s.text = `

my logic goes here

`;

(document.head || document.documentElement).appendChild(s);

Will my script injection will get stopped? If so what alternative should i use?


Thanks,

Yureshwar Ravuri

Simeon Vincent

unread,
Nov 29, 2021, 8:55:18 PM11/29/21
to Yureshwar Ravuri, Chromium Extensions
Will my script injection will get stopped? - Yureshwar

This is currently forbidden by the Additional Requirements for Manifest V3 section of the Developer Program Policies. This section specifically highlights that extensions cannot "Including a <script> tag that points to a resource that is not within the extension's package."

In other words, if the Manifest V3 version of your extension included the sample code you provided in your email, I'd expect it to get rejected at review time.

If so what alternative should i use?

That depends on the use case. If your extension is used on managed devices (for example, enterprises or education), then your customers can continue to do what you're doing and use enterprise policies (ExtensionSettings or ExtensionInstallForcelist) to force-install the extension on users' machines.

If you have to publish your extension to the Chrome Web Store and can bundle the extension's logic with the extension, you can use chrome.scripting.executeScript to inject a file or function directly into the page's world. See the "world" property on ScriptInjection for more details. 

If you want to inject an arbitrary script, things get more complicated. We are planning to add support for "user scripts" to the chrome.scripting API, but I'm not sure if the experience shown in the videos you shared would be considered an acceptable user of this capability. At the moment we're considering positioning dynamic execution of user scripts as a power user or developer focused feature due to the inherent risks around arbitrary code execution.

As such, in this case your best route might be to implement an automation system that uses declarative commands to script user interactions rather than generating raw script and injecting it into the page. The main thing you'd need to be careful of, though, is that this automation system should not allow users to execute arbitrary commands or be used to compromise users. This system will need to be audible by the Chrome Web Store review team in order to verify that it does not pose a risk to end users.

Simeon - @dotproto
Chrome Extensions DevRel


--
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/e1f793d4-69fc-478e-b6d7-184420a6a927n%40chromium.org.

Alexei Miagkov

unread,
Nov 30, 2021, 12:55:47 PM11/30/21
to Simeon Vincent, Yureshwar Ravuri, Chromium Extensions
Simeon, I think you misunderstood the question. I believe this is yet another request for crucial functionality broken by Manifest V3, the ability to inject your scripts into frame contexts before anything else happens in those frames.


Simeon Vincent

unread,
Nov 30, 2021, 1:23:45 PM11/30/21
to Chromium Extensions, Alex, yure...@gmail.com, Chromium Extensions, Simeon Vincent
Right, due to the Additional Requirements for Manifest V3 section of the Developer Program Policies, the approach that developers use in Manifest V2 to inject a script into a frame before other code runs is not possible in Manifest V3 extensions in Chrome. We are planning to address this gap by expanding scripting.registerContentScripts to allow developers to specify an ExecutionWorld similar to the recent update to scripting.executeScript.

Simeon - @dotproto
Chrome Extensions DevRel

To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extensions+unsub...@chromium.org.

--
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.

Alexei Miagkov

unread,
Nov 30, 2021, 1:53:16 PM11/30/21
to Simeon Vincent, Chromium Extensions, yure...@gmail.com
Manifest V3's CSP is the thing that breaks injection. Developer Program Policies shouldn't apply here; the code being injected is indeed part of the extension's package, no "fetching from remote source".

Regarding your plans, when will this gap be addressed? How do you square the 2022 deprecation timeline with these gaps? Page/frame context script injection is broken, observational webRequest is broken, native host communication is broken, ...

To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.

--
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.

Alex S

unread,
Nov 30, 2021, 2:02:00 PM11/30/21
to Chromium Extensions, Simeon Vincent, Alex, yure...@gmail.com, Chromium Extensions
Thanks for the info on the update to RegisteredContentScript.  To clarify:

1. Is it accurate to say you're planning to update RegisteredContentScript to something like:
{
  allFrames?: boolean,
  css?: string[],
  excludeMatches?: string[],
  id: string,
  js?: string[],
  matches?: string[],
  persistAcrossSessions?: boolean,
  runAt?: RunAt,
  injection?: ScriptInjection
}


2. ScriptInjection includes a non-optional tabId.  Will we be required to provide a tabId when passing in ExecutionWorld into the registerContentScripts api or will it be possible to register for all tabs?

3. With the proposed addition of ExecutionWorld to registerContentScripts, would it be accurate to say that if we had some javascript like below, then window.foo would be available to the frame synchronously?:
//service worker
const scriptsToRegister = [
  {
    id: '_1',
    matches: ['*://*/*'],
    js: ['/inject_foo.js'],
    runAt: 'document_start',
    injection: {
      world: "main",
      tabId: //see question 2 above
    }
  }
];
chrome.scripting.registerContentScripts(scriptsToRegister);

// inject_foo.js
window.foo = 'foo'

Thanks Again!
Alex

Alex S

unread,
Nov 30, 2021, 2:11:53 PM11/30/21
to Chromium Extensions, Alex S, Simeon Vincent, Alex, yure...@gmail.com, Chromium Extensions
As a follow up to (other) Alex's point above, would you consider enriching the content script's CSP allow list to include web accessible resources.

What I mean is that the following content script will run with MV3:
const script = document.createElement('script');
script.type = 'text/javascript';
script.setAttribute('async', 'false');
script.src = chrome.runtime.getURL('inject_foo.js'); //inject_foo.js is in web_accessible_resources
const container = document.head || document.documentElement;
container.insertBefore(script, container.children[0]);
container.removeChild(script); But the following will fail with a CSP error :
    fetch(
chrome.runtime.getURL('inject_foo.js'))       .then((content) => {
        
const script = document.createElement('script');
script.type = 'text/javascript';
script.setAttribute('async', 'false');
script.textContent = content; //same content as inject_foo.js is in web_accessible_resources
const container = document.head || document.documentElement;
container.insertBefore(script, container.children[0]);
container.removeChild(script);
    })

From a security point of view aren't these 2 equivalent, the only difference being that we are able to inject a script inline instead of asynchronously.

Thanks!
Alex S

Simeon Vincent

unread,
Nov 30, 2021, 9:15:07 PM11/30/21
to Alex S, Chromium Extensions, Alex, yure...@gmail.com
Manifest V3's CSP is the thing that breaks injection. - Alexei

I was wrong; thank you for the correction and for highlighting the impact on this use case.

As you indicated, Manifest V3 does introduce a CSP change for extension content scripts that prevents content scripts from adding arbitrary scripts to a page. I believe the default CSP applied to content scripts is "script-src 'self'; object-src 'self';"

For some unnecessary additional context, we originally planned to add a default CSP to content scripts (aka isolated worlds) and allow developers to override that value using an "isolated_world" property on the "content_security_policy" object in manifest.json. Later, we revised the extension CSP design to not allow isolated world CSP overrides, we removed the relevant key form the CSP object. When this change landed, I mistakenly thought that we also removed the default CSP for the isolated world, but clearly we did not. Sorry for the confusion.


Developer Program Policies shouldn't apply here; the code being injected is indeed part of the extension's package, no "fetching from remote source" - Alexei

I can see how the current policy language could be interpreted this way, but that interpretation does not match my understanding of the intent of the policy or our enforcement practices. 

"Remotely hosted code" and "remote" as used here are terms of art with respect to the Chrome extensions platform and policies. It effectively means any code that is not a static file in the extension's package. That's not a strict definition, though, as "code" is a bit of a nebulous term and we also allow functions defined in packaged static files to be serialized as strings and injected into a page using scripting.executeScript. 

Beyond that, though, the term also applies to the method of execution. Loading a static file in the extension's package using the scripting API is allowed, but setting a script element's innerText to a JS string (even a const literal) is not. 


I'll be raising the concerns shared here related to the default content script CSP and remotely hosted code policy with the appropriate team members internally.

Simeon - @dotproto
Chrome Extensions DevRel

Alexei Miagkov

unread,
Dec 1, 2021, 10:01:38 AM12/1/21
to Simeon Vincent, Alex S, Chromium Extensions, yure...@gmail.com
The real takeaway here is that a use case fundamental to privacy and security extensions that worked in Manifest V2 is utterly broken in Manifest V3.

It's not that Google extensions policy docs are misleading, it's not that developers for some mysterious reason want to assemble scripts out of strings and the new CSP breaks that. No. It's that WE ARE NO LONGER ABLE TO INJECT SCRIPTS into frame contexts before anything else happens in those frames.

Google announced that Manifest V3 is ready and that Manifest V2 will be gone after 2022. But regardless of what Google says, Manifest V3 is not ready, and we are left hanging waiting for this and other crucial use cases to be restored.

A solution to this use case that we could test (such as registerContentScripts() with 'world': 'MAIN') would be great. There will be unhandled edge cases and bugs. Does the solution handle injecting into Service Workers correctly? Does it bypass page CSPs (it should!)? How do we send configuration parameters into it? All of this waits on having a solution to work with.

Alex S

unread,
Jan 4, 2022, 4:04:38 PMJan 4
to Chromium Extensions, Alex, Alex S, Chromium Extensions, yure...@gmail.com, Simeon Vincent
Hi Simeon,

Happy new year!

I wanted to check in to see whether the team had any thoughts on:
Disabling the isolated worlds restriction on default CSP for content scripts.

Thanks!
Alex S

Simeon Vincent

unread,
Jan 6, 2022, 2:30:02 AMJan 6
to Alex S, Chromium Extensions, Alex, yure...@gmail.com
I wanted to check in to see whether the team had any thoughts on:
Disabling the isolated worlds restriction on default CSP for content scripts.

Sorry, but I'm not sure what you mean. Could you rephrase the question or share a bit more context on what you're trying to accomplish?

Simeon - @dotproto
Chrome Extensions DevRel

Alex S

unread,
Jan 6, 2022, 4:00:34 AMJan 6
to Chromium Extensions, Simeon Vincent, Chromium Extensions, Alex, yure...@gmail.com, Alex S
I was responding to your last message on Nov 30 "I'll be raising the concerns shared here related to the default content script CSP and remotely hosted code policy with the appropriate team members internally." And wanted to find out whether the team was going to change the default content script CSP to allow the use case discussed in this thread. 

Simeon Vincent

unread,
Jan 20, 2022, 6:55:20 PM (6 days ago) Jan 20
to Alex S, Chromium Extensions, Alex, yure...@gmail.com, Alex S
No, the CSP change was made with the intent to provide developers with other ways to accomplish main world injection. We added support for specifying which world executeScript() injects into in Chrome 95.

In the future we are planning to add world specification support to both static and dynamic content script registration. We are also planning to add func/arg support to dynamic content scripts.

Simeon - @dotproto
Chrome Extensions DevRel

hrg...@gmail.com

unread,
Jan 20, 2022, 8:00:54 PM (5 days ago) Jan 20
to Chromium Extensions, Simeon Vincent, Chromium Extensions, Alex, yure...@gmail.com, Alex S, Alex S

In the future we are planning to add world specification support to both static and dynamic content script registration. We are also planning to add func/arg support to dynamic content scripts.

Do you plan to add those new features while MV2 is still supported?
Keep mind that we need at the very least a few month for migrating and testing our new MV3 implementation.

 

Simeon Vincent

unread,
Jan 25, 2022, 2:29:27 AM (yesterday) Jan 25
to hrg...@gmail.com, Chromium Extensions, Alex, yure...@gmail.com, Alex S, Alex S
Yes, we intend to add these features while Manifest V2 is still supported. 

Simeon - @dotproto
Chrome Extensions DevRel

Reply all
Reply to author
Forward
0 new messages