-
Notifications
You must be signed in to change notification settings - Fork 56
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
User scripts in Manifest V3 #279
Comments
@dotproto (on behalf of Google / Chrome) announced the intent to support user script managers in the WECG meeting at TPAC (#232). The meeting notes have been merged in #277 and this topic can be found under "User script manager support in MV3" at https://github.com/w3c/webextensions/blob/main/_minutes/2022-09-15-wecg-tpac.md I (on behalf of Mozilla / Firefox) previously stated that we'd like to support user script managers, ideally in a more secure way, at https://blog.mozilla.org/addons/2022/05/18/manifest-v3-in-firefox-recap-next-steps/#comment-227473. EDIT: The API design is ongoing. Significant updates are listed here:
|
To recap from https://github.com/w3c/webextensions/blob/main/_minutes/2022-09-15-wecg-tpac.md, the proposed API is:
My concern with this proposal is that it re-introduces the ability to execute arbitrary code in a (somewhat) privileged execution context, against all efforts to remove this from MV3. In practice, given the absence of anything better, user script managers already execute (third party) user script code in a content script, which shares the extension APIs and some privileges with extensions. This is a suboptimal design. I propose the following API to support user script managers, which is more secure by design:
Not security-related, but still relevant to consider in the API design:
|
I agree with this concern. chrome.scripting.globalParams was added to solve similar use-cases however it's not ever exposed to the main world scripts. I'd instead propose a way to allow these variables to be passed into the script (perhaps cloned so that modification isn't possible) some avenues to inject these would be:
I'd not expose these on globalThis/window as ideally the page would have no visibility of these parameters. |
@dotproto @Rob--W thanks for addressing this now.
Will this be automatically set to
This sounds promising and will make securing a lot of functions and prototypes that can be altered by the page obsolete.
This is a problem. I'd say more than the half of the userscripts directly interact with the page's JavaScript objects and functions. Tampermonkey at Firefox (BETA for now - the stable release will follow soon) for example uses Firefox's userScripts API which creates a context separated from the page (and the extension), but still allows access to the main world (unsafeWindow).
👍
Userscripts should not be limited by a "foreign" CSP (extension or main world) . They are made to do things that neither Tampermonkey nor the page expect. Ideally we could add a |
I second @derjanb concern with limiting interaction via DOM APIs. This limits what can be done in terms of userscripts. Being able to mess with the webpage JS is a key point. I also liked how Firefox implemented the |
Yes. Webpages can run code before userscript managers would ever be able to by using iframes or popup windows. It has been used maliciously in the past and is now partially fixed in some userscript managers, however there is no complete 100% fix. The issue of webpages being able to execute code before extensions was reported to chromium some time ago and was marked as wontfix iirc |
Currently we can execute arbitrary code in MAIN world on Chrome 107 with these code:
Most user scripts do not need to as complex as Greasemonkey-like scirpts:
Just like users execute scripts in the DevTools "Console" or "Source -> Sinppet", but use extensions to execute scripts automatically base on the page url. We can create a lite version user script manager with Manifest V3 now. But does the Chrome Store policy allow this usage? |
Hi everyone! I started an API proposal doc that takes into account the points discussed here and in offline conversations. The goal is to align on an API design that works better for everyone. Please, feel free to comment on the doc or in this issue. Also, I'll be attending the next WECG meetings for further discussion. Looking forward to working together |
Does the current proposal imply that a user script will only run on a page? |
Methods that contain |
The main problem is that this API proposal is currently unusable in Violentmonkey or Tampermonkey because it's completely insecure due to https://crbug.com/1261964, to circumvent which these extensions currently have to extract the safe methods from a temporary iframe before running the main world scripts. It means that the main world script cannot call any standard method like addEventListener until the extracted methods are passed securely from this iframe in a manner that cannot be intercepted/spoofed by another main-world script. Unless this bug is fixed or a secure communication method is provided, these extensions will become wide-open backdoors and I will suggest their authors to remove them from the web store. The method must be synchronous, by the way. |
Another nasty problem is that the API proposal doesn't support |
@tophf: I made some suggestion changes to the document. They haven't been approved but I think it's worthwhile for you to take a look at them and check if they suffice. |
User scripts will only be allowed to execute in the MAIN world (page) or a new USER_SCRIPT world. |
Is there some way to provide additional functionality (GM.xhr and friends) to a user script? For example the Firefox |
@Sxderp It's there. Just not much fanfare calling to it:
This is inside "Other considerations" sub-chapter |
I would suggest holding a separate topic-specific meeting rather than discussing it in a regular meeting. Browser vendors and scripts manager maintainers are invited to participate. (PS: I am not script manager author)
I recommend using a completely different namespace(e.g. My other thoughtsWhat I understand is this proposal still allows arbitrary local and remote code to be executed in the main or userscript world of web pages, just don't allow to use extension api. Besides extension and theme, can the web store support a third type of user script? All user scripts are submitted to the store and reviewed? Thus, user scripts are trustworthy and deterministic like extensions. Compared to user scripts, I think content scripts should also allow arbitrary code execution. Because, when websites changed their web pages's structure/code/style, content scripts also need to be updated quickly to adapt to changes.(Usually, extenson developers do not own the site) |
This comment was marked as off-topic.
This comment was marked as off-topic.
The extension needs additional permission for it. Thus the market can warn users that it's a potentially dangerous extension, also, reviewers will check if it's a valid usage of usercripts, like e.g. a weather app doesn't need it and it will very suspicious if it asks for it.
No. Sometimes you need US only for yourself, and sometimes even for a short period of time. Also, if a US need only a very limited number of people (<10), there is no reason to "publish" it.
Enforcing security is one of the main goals in the MV3, and forbidding arbitrary code execution is one of the main ways to achieve it.
Sites do not roll up changes every single day, most of them even prefer to avoid this (it requires spending money and receiving usually angry feedback that things anymore aren't what the user used to, unless it's bug fixing). Also, you can in an empirical way find general and fuzzy approaches that are more or less resistant to minor changes in the page layout. |
I understand. In my previous comment, I said "script manager can supports run both trusted and untrusted code, but gives different user warnings.". In other words, no matter it is published to the store or not, users can run them.
This question is best answered by the extension stores. I don't know what they think.
In this way, I think user scripts should be subject to the same restrictions as content scripts.
I often see extension developers complaining that a website update caused its code to go wrong, and they need to update the extension immediately. |
First off, As for the separate methods, correct me if I am wrong, you are suggesting having separate methods for user scripts, content scripts and page scripts (basically dividing content and page scripts) or either changing the current content script methods (issue #313). Content and page scripts behave similarly, have the same permissions enforcement and most importantly they don't support remote host code. Thus they can be grouped under the same methods (as they are currently) with different worlds. User scripts have to be clearly differentiated for better documentation and stronger enforcement of remote host code abuse. Thus the introduction of new methods. However, as @hanguokai points out, maybe is better having a new namespace. As for your rename suggestion, I see the issue is listed as an Agenda discussion for public meeting on 2022-11-10 so better to follow up there.
I was not aware of this issue. I'll contact the OWNER and see what's the status on this. Thanks for pointing it out
How are RegExp currently supported in MV2? I believe Sorry for the late response everyone. I am getting myself familiar with user scripts and user scripts managers to provide better answers. Will continue shortly. |
As I pointed out in #313 they are so different that you could say they're "worlds apart", pun intended, so conflating them is a very dangerous path that misleads developers into believing their data and code are safe from interception/spoofing/poisoning.
There's no support at all. The closest thing is RE2 syntax in filtered events of declarativeContent or webNavigation API. Currently userscript managers explicitly use I understand that Chrome won't add full RegExp to its API, so the next best thing is implementing RE2-compatible |
@EmiliaPaz Thanks for sharing your proposal! I'll share my feedback here, because it's difficult to trace or reference discussions on Google docs, especially on a document that's still undergoing revisions. Your stated goal of the document is "Achieve functional parity with MV2 for user script managers.". I note that just MV2 parity is a low bar. Due to the lack of supporting APIs from the browser, user script managers are built insecurely. Improving that would be great. I'll describe the needs of user script managers in more detail, particularly focused on security and feasibility. After that I'll summarize the requirements as a starting point for the API design. I am intentionally focusing on parts that cannot be implemented by user script managers themselves, as these should be the top priority. E.g. regex matching can be implemented by user script manager code themselves, and support for that could be a future enhancement. BackgroundThere are many user script managers (USM hereafter), with the most popular ones being Greasemonkey, Tampermonkey and Violentmonkey. This section describes how they work, and the core primitives that they rely on today. Other than the "userscript" world, all concepts mentioned here already exist in MV2 today. User scripts run on top of existing web pages, and need to access the DOM and/or JS variables in the page's context and/or semi-privileged user script APIs:
The following questions are relevant for the choice of world for a user script:
When semi-privileged APIs are not needed, a USM only needs the ability to run some given string as JavaScript code. Ideally in a world distinct from the page/content script, i.e. the "userscript" world proposed in #279 (comment).
This is generally the structure of any script that introduces semi-privileged functionality to the main world. It itself runs in the main world (the concept is also relevant outside user scripts): (function(secrets) {
// Step 1: Save a reference to all standard DOM API methods, to avoid tampering by the web page.
// Step 2: Use |secrets| and DOM APIs to create a semi-secure communication channel, e.g. using `CustomEvent`.
// Step 3: Via this semi-secure channel, retrieve necessary data such as user script metadata.
// Step 4: For *each* user script, create the GM API interface and execute the user script:
somehowExecuteUserScript(localVarWithGMAPI, window, etc);
})("secret communication ID here"); Ordinarily, web pages and also scripts in the main world can use window.someSecretRandomName = function(GM, unsafeWindow, etc) {
/* actual user script code here */
}; The user script is wrapped in a function, because it needs a closure with a reference to the semi-privileged API, which it receives when called by the previous script that starts with Identified requirementsThe following required primitives can be derived from the above overview of how user script managers work:
@EmiliaPaz 's proposal in #279 (comment) covers the first two aspects, but not the other two. There are many different ways to implement these requirements. I will show two examples, one userscript-specific API (from Firefox) and a more generic API that has broader applicability. Final note: the above requirements are minimal. If the goal is to move the responsibility of matching and triggering script execution from the extension to the browser, then there should also be a way to register some metadata for a script that is synchronously available. It would also be nice if there is a way for content script to veto the execution of a user script. These can be supported in the two API designs below. Firefox's userScripts API (MV2)Firefox's userScripts API was mentioned before in #279 (comment). I'll briefly describe the relevant parts of the API design for inspiration. Features of the
In Firefox, it is possible to have asymmetric access relationships between code from different execution environments (Xray Vision). This mechanism enables user script managers in Firefox to prepare the environment beyond what's possible with The Note: we have marked the userScripts API as MV2-only in Firefox because the script registration mechanism is incompatible with the lifetime characteristics of background scripts in MV3. Furthermore, we would like to establish a cross-browser-compatible API for user script managers. Scripting API with cross-world communicationTo avoid confusion, this example extends the current
// Somewhere in the extension, e.g. extension page where the user edits the user script.
chrome.scripting.registerUserScripts({
code: `
// This is what the user script manager generated:
let GM = {
info: GM_info,
};
let unsafeWindow = window; // In the main world, unsafeWindow is the window.
let someRandomNumber = args[0];
args = undefined;
// This is the actual user script:
console.log(hello, GM.info(), unsafeWindow);
// ^ note: console is a global variable. The web page could have tampered with it...
`,
externalArgs: ["hello", "GM_info"],
args: [4], // <-- someRandomNumber
id: "my-userscript",
world: "MAIN",
matches: ["https://example.com/*"],
}); Internally, the browser could convert the above to the following: function(args, hello, GM_info) {
/* the code string here */
} // TODO: browser should find the hello & GM_info args and call this function Then, before the browser runs the user script, it asks the content script for the API definition. For example: chrome.scriptingContent.onArgRequest.addListener(arg => {
if (arg === "hello") {
// We must at least support primitive values (string, number, etc).
return "hello world";
}
if (arg === "GM_info") {
// We must also support functions. Potentially async (i.e. returning a Promise).
return async () => {
// The functions themselves may return values. TODO: define acceptable return values.
return { plain: "object", is: "safe", but: "what", about: Function ? "callable properties" : "?" };
};
}
}); To maximize utility, I suggest to support at least the following return types:
The above description consists of standard types that are well-supported across browsers. Objects with getters, setters or function properties are not supported. Note: the above is intentionally generic to cover broader use cases such as #284. |
Is XHR necessary or can it be shimmed using fetch? Key constraint is XHR supports blocking requests. |
Do you, or someone else, know how close do we get with:
EDIT: I just realized @Rob--W commented, and included regex. Will go over it and comment back |
Proposal, that takes into account multiple points discussed here, was moved to PR #331 to facilitate discussion |
Just want to point out, that there are other use cases for injecting user scripts than just by match patterns. Example add-ons with code/implementation reference: Therefore I plead to have a |
This proposal is part of #279 Co-authored-by: Emilia Paz <emiliapaz@chromium.org> Co-authored-by: Simeon Vincent <simeonv@google.com> Co-authored-by: Rob Wu <rob@robwu.nl>
This is implemented in Chrome. Future expansions will be tracked separately (you can see some of these in @Rob--W 's comment at #279 (comment)). We'll leave this issue open until other browsers implement the core API, and then close this out. |
PLACEHOLDER: We have a couple of issues related to user scripts support in Manifest V3, but nothing that currently feels like a good tracking issue. This issue intends to fill that gap by consolidating discussion of Manifest V3 API considerations in one place.
The text was updated successfully, but these errors were encountered: