Introducing chrome.scripting
developer.chrome.com
developer.chrome.com
I find it very unfortunate that the capabilities of browser extensions are being crippled. I understand that there are significant security issues with browser extensions, but the same general purpose APIs that allow abuse simultaneously allow really wonderful and powerful things to be built. As a developer who loves extending and personalizing their browser, it's simply depressing to see that go.
Sure, there are significant security issues. Since when is that a reason to disable a user-originated threat vector? As long as the user in question is informed and alerted to the potential security risks shouldn't it be within the user's purview to decide what to allow and what not?
Even if this line of argument cannot be said for every purpose - and I understand there is a potential for abuse and misinformation about misrepresenting any specific extension - but for instance say Tampermonkey, which the user needs to first download from the webstore then the user needs to also download the script, can't there be sufficient warning that what the user is doing is potentially harmful? Or a requirement from the webstore that Tampermonkey somehow also alert users before loading any remote scripts?
If a user decides to downright download malware we let them (Given, Chrome would block it but you can override that manually) why wouldn't the user be allowed to override these risks (i.e. you can enable it only in development mode etc. with a requirement that such extensions provide sufficient warnings etc.)
If you've been following the Epic v. Apple case, you'd know some folks like Tim Cook strongly believe the answer is no, or in his words "they shouldn't have to [decide]."
The freedom-less future sure seems pretty bleak.
Suppose Facebook decided to move to a different third party store on iOS, maybe their own store, so they don’t have to list their data access and sharing policies, don’t have to go through app store review, etc.
Doing that forces me to choose between rigorous app review and disclosure, and using the Facebook app. I don’t want to be put in that position. One of the reasons I use an iPhone is because of that.
How is that any better that being responsible for making the choice in the first place?
We don't all have time to sit around evaluating 1,000 similar packages, compiling and debugging them from scratch, just to get a simple app or game working.
The bleeding edge will keep on bleeding, but for the rest of us, good enough is good enough. It doesn't have to be perfect, it just has to work well enough and not add to our already-overwhelmed mental loads.
and here I think is the issue - it's hard for a closed source project to fully inform and alert anyone, at all. It's impossible to get a full understanding of a codebase that doesn't allow me to look at it, and I don't see why that would be different here. I can't understand security risks to Chrome (proper Chrome, not Chromium) because I'm not allowed to, therefore any extension at all could be dangerous in some way. So it is actually best to not allow the user to think about security for themself, because they can't have the necessary information. A developer can't look over every extension because they have better things to do with their time, so I think it makes sense that we end up with this incredibly restricted platform.
If your strategy for security can't be having an open and audited interface and implementation, the next best thing seems to be no interface.
But yes, I agree that it's not as simple as my original comment made it out to be - I definitely failed to fully acknowledge that most/some of the critical parts are open source and secured, but I think the incompleteness in any outside understanding (such as my own) is a major factor in the options Google could present about security.
Since Google is operating at a scale where the majority of users use their browser, so a successful popular malicious extension scales extremely rapidly. This is basically a recapitulation of the decisions Microsoft had to make regarding the market dominance of Windows and the ease of attacking users via VBScript exploits. The developers of the framework have to make a trade-off between capabilities of the framework and likelihood that those capabilities will be used to attack the average user. It's a cat-and-mouse game where there are not obvious technical answers so much has move-countermove.
We even have the analog to Apple Computer during the heydays of VBScript exploits in this story... With its much smaller market share, Mozilla has the luxury of worrying less about these exploit vectors because successfully deploying a malicious extension in that ecosystem only impacts a couple percent of total users of the internet. Much as Apple didn't have to worry much about malicious AppleScript exploits.
Google is trying to solve a similar problem here to the one they have to solve with App Store apps: the ability to make claims about safety an end-user can trust. They can't make those claims if the extension can modify its behavior without any way for the Web Store administrators to know.
In a purely ethical sense, absolutely yes. But we're coming up on 30 years of people using the internet, and it's been clear for a while now that you simply cannot teach people what is safe and what is not in an absolute sense. Even highly technical, experienced users still make mistakes and install malware sometimes. Informing users is not effective, to a first approximation. System designers have a responsibility to protect the users of their systems.
> If a user decides to downright download malware we let them (Given, Chrome would block it but you can override that manually) why wouldn't the user be allowed to override these risks (i.e. you can enable it only in development mode etc. with a requirement that such extensions provide sufficient warnings etc.)
These overrides should exist, but making them too easy will just lead to malware tricking people into triggering them. And some doors are so frequently abused or fundamentally vulnerable that they probably should be closed entirely — most people don't think we should still be embedding Java and Flash in webpages these days.
It would seem like a useful compromise to have harmful features/functionality disabled by default for each new script - controlled at the individual script level.
If the user wants to invoke/allow the feature, they should be able to explicitly and manually enable it. Like the android app permissions: Allow access to x? [none, this time or always?]
And when there are hundreds of features... Scratch that. Even if there are ten features, the user will simply click "allow all" without paying attention to what's requested.
More and more Android has been lumping disparate access permissions together with the goal seeming to be KISS.
The people who need this functionality are a very small minority. Tampermonkey has 10M installs which is phenomenal, but Chrome apparently has an estimated 2.5B active users. The tradeoff here is exposing billions of users to unnecessary risk, to save two orders of magnitude fewer of the most tech savvy users from an insignificant annoyance. I.e. just use a browser that supports the extensions you need instead.
The basic point of my comment is that deprecating the capabilities or the current API just because there can be a security risk in some cases for the average user is harmful to the more advanced users.
You focus on one possible solution mentioned about warning dialogs. However, there are lots of different solutions available which would allow it to run only with knowing 100% that the user knows what they're doing aside from warnings.
There can be a command line flag --developer etc. just like there is for unsafe certs.
'Use a browser that supports it' is not a solution since - as you said - Chrome has the largest user base why would a developer put in the effort to develop a solution for a minorly used browser.
Since the major browser is closing this API there will be no possible use of this type of functionality for anyone - even the users who know what they're doing.
I wish I still had that kind of innocence.
Malicious extensions are probably the biggest existential threat to the web as a platform. If browser regain the reputation for being insecure that they deservedly had 15 years ago, more and more serious business will move into mobile app walled gardens. This has to be solved.
But rather than accept the simple explanation, we get these inane conspiracy theories on what the true motivation is. No, it's not about ad blockers because the subject of this blog post is not a feature that ad blockers would use. And the same for the half dozen alternative explanations.
Seriously, what is wrong with you people? Can't you at least save the high school level cynicism for situations where an assumption of malice makes some sense?
Got any stats on what percentage of the browser install base has even one extension installed? Then we can come back to your "tHe biGgEsT eXisTenTiAL ThReAt" nonsense.
And how an assumption of malice doesn't make sense when we're talking about the world's biggest ad company doing something in the name of security that happens to cripple ad blockers -- well, suffice to say, you're probably not cut out for journalism.
Now go get some rest?
Most users don't need that level of power or customization and it just opens up not only attack vectors but general UX confusion. Hide that sort of thing behind an admin mode or whatever, but otherwise, yes, PLEASE hide dangerous functionality so people aren't exposed to them.
Users aren't asking to be treated like children, they just don't want to have to think about zero-days and layers of config menus because some developer in an ivory tower valued "muh freedoms" too much.
Wonder how long that'll be an option. I use FF for all my browsing and its amazing how much stuff breaks if you're not using chrome. I'm thinking the re-captcha stuff should be used as evidence in a google anti-trust case :-P "Oh, your on firefox? here...lets identify all these pictures.."
Imagine it this way: The local supermarket is selling a product which claims to be food but actually contains a highly toxic poison. And then someone justifies it still being allowed because it's still up to the buyer to choose to buy and consume it. It's on the user, the should be responsible to look for trusted brands that do not disguise poison as food or they could take it down to their local lab to test it for toxicity before consuming it.
It's obviously completely absurd to expect the user to protect themselves from malice like this which is rampant on browser extension stores.
Basically anything on sale if had in the wrong dose. Example: a can of a sugary drink is OK, drink 6 of them per day and it's going to be bad for your health.
Let's try a different metaphor.
If this doesn't work for your specific use case, write a wrapper object - your point is that the API was stable with V2, but it will still be with V3 and you should be able to rely on that.
Am I missing something?
I doubt that tampermonkey executes custom scripts within content script sandbox since a script could take over the extension itself. They should be fine.
Please note that as an extension developer I receive at least once a month a cash offer to inject scripts that track users.
The ability to execute arbitrary JavaScript in content scripts at runtime. Remote-browser works by making it very easy to run code in content and background script contexts from a remote client. Typical browser automation tasks like filling out an input, clicking a button, or extracting the HTML of an element are accomplished by marshaling code and results between the browser and the client.
your point is that the API was stable with V2
My point isn't that the API was stable, it's that Google is moving towards removing key features from the API because they consider them to be too powerful. Blocking webRequest and executeScript are two notable examples.
> instead of tons of browser-specific implementation code and a custom automation API.
Half the time now, I just close tabs because I'm not sure that lil 'x'(close) on the ad that popped up isn't part some malware. When its too easy to duplicate 'official' looking stuff, people become numb to seeing it all the time.
A.k.a. the “line of death”: https://www.theregister.com/2017/01/19/browser_line_of_death...
At least now I know its not just me having these issues.
Thanks!
however I see no reason why firefox should follow chrome on this? Also my natural paranoia in regards to the motivations of Google make me think maybe executeScript is too powerful and allows the extension makers to do things that are not malignant, but just against the corporate interests of Google.
I would love to hear more about your personal project ideas that involve remote-browser. My contact info is in my profile, feel free to reach out.
Just one example of the many disingenuous arguments in this post.
They didn't need to start from scratch to achieve the stated goals of security and performance. For Manifest V3 to be a rational conclusion, there must be additional unstated goals. Such as destruction of ad blockers, a desire to no longer maintain extension support or Chrome Web Store, or the need to run CWS with a skeleton crew.
None of these unstated goals benefit users or developers which is why we have to endure a gaslighting campaign about how smart and great Manifest V3 is.
I think extension developers have been crystal clear from day one about how regressive this change is.
Isnt that what google normally does? Instead of fixing an existing product, throw it away and introduce a new shiny thing, that does the same thing.
I think if Manifest V3 had 1:1 capabilities with MV2, less people would care.
Google has oodles of devs and infinite money; so their culture doesn't balk at rewrites. In the real world, treading water to stay on the Chrome Web Store with MV3 will muscle out huge swaths of a company's product roadmap. Our execs didn't even know what manifest versions are a year ago. Now Google is on everyone's shit list. If your API change is so jarring that non-technical people have to think about it, you're doing it wrong!
This is less of an API change and more of a platform redefinition.
Introduce a new thing, that does the same thing but worse*. Google Music being replaced with YouTube Music is a great example of this.
Blog post author here. This comment is incorrect on two main fronts.
First, the Chrome Web Store's Developer Program Policy did not prevent the use of remote code, it only forbade the obfuscation of remotely loaded code. An alternative, stricter reading of the policy was that extensions could not use remotely hosted code to obfuscate it's operations. Regardless of which of these interpretations you favor, using remotely hosted code in Manifest V2 extensions is not forbidden by our policies.
Second, I strongly disagree with the implication that policy changes could have addressed the abuse issues we're seeing. Even if we did have policies disallowing the use of remotely hosted code, that does not somehow compel developers to comply or simplify the enforcement process. I have a ton of respect for my colleagues in review, but policy enforcement is complex and virtually impossible to get right 100% of the time. So, some amount of malware will get through review, some number of users will be exploited, and some amount of harm will result. How much harm should we accept as "the cost of doing business", especially when we have a way to address a major exploit vector?
Speaking as a developer, I'm not exactly thrilled to lose capabilities that I've been using responsibly because other people are exploiting them. On the other hand, as a member of the team maintaining this platform I don't see a practical alternative to address the problems that arbitrary code execution presents for the average user.
> Your extension should avoid using remote code except where absolutely necessary. Extensions that use remote code will need extra scrutiny, resulting in longer review times. Extensions that call remote code and do not declare and justify it using the field shown above will be rejected.
[End quote]
This has nothing to do with code obfuscation. Remote code in general is heavily discouraged. Your extension can be outright rejected if your 'justification declaration' is insufficient (Google's discretion). And if that isn't enough to deter you, the review time will also suffer (Google's discretion.)
Does this policy not work? Surely it has led to a reduction in remote code exploits. And also given the enforcement team a straightforward path to take down an app in violation.
To your second point, you _don't_ have a way to address a major exploit vector. You've thrown the baby out with the bathwater. You've banned cars and introduced chariots as the solution to hit and run accidents. Now nobody can be run over! We've fixed Google Roads!
I would also like to know what API did exploiters share with ad-blockers? At the time, we were told the ad-blocker APIs had to be removed for performance reasons. Has the argument changed to a purely security one? Was it both?
The MV3 genie has sadly been let out of the bottle. We can't go back. But we can reduce its capability diff with MV2. It will involve sacrificing some of Google's secret objectives, which is why it's important to know them.
Listening to performance arguments one day, then security arguments the next, in carefully worded statements that don't quite add up; is what gives the impression there are secret objectives.
While the capability for running extensions on mobile chrome has always been there and is quite evident with the chrome forks like "Kiwi browser" which runs every chrome extension including ublock just fine.
It only shows how Google must have deliberately decided to purposely never support extensions on mobile from day one.
I mean it's much harder to give something and take it back, so you generally phase out functionality out by citing security issues and that's what I think is this whole v3 fiasco is all about too.
I use less and less extensions, not even the dark mode ones now that websites are changing too (I wish HN would too)
Play store download numbers are meaningless for a pre installed app. Chrome is installed by default on all Android phones and you cannot remove it. If you disable it, often some other things like webview do not work well.
"No, you shouldn't use Brave.": https://web.archive.org/web/20210531085250/https://aspenuwu....
But the Firefox rewrite isn’t handling all extensions well.
Container Tabs break hilariously, spawning tenthousands of tabs.
Tampermonkey and similar extensions that spawn popup windows or custom tabs fail, too.
Sidebar extensions like vertical tabs break as well.
But you can get them to work :)
Lots of people complain about it. Maybe fewer for a few years now that we know it is missing and Google really doesn't care about adding this feature... ever.
[0] https://bugs.chromium.org/p/chromium/issues/detail?id=896897...
EDIT: I'm referring the the 'Manifest v3' update as a whole, not to the specific API change discussed in the article
The change described here is something else under the same umbrella. Not the change he was talking about. But generally, the whole of "manifest v3" will render lots of useful extensions dead in the water. Any heuristic ad blockers, things like tampermonkey, etc. If you want things like that, you'll have to move to Firefox.
[0] https://groups.google.com/a/chromium.org/forum/#!topic/chrom...
This API change is making it worse for Tampermonkey than for malware.
"Malware" extensions canstill be explicitly "sideloaded" to Chrome in developer mode. Closing this API means Tampermonkey won't be able to run even when sideloaded. If this was truly their only concern they could have just blocked Tampermonkey and comparable extensions from the webstore. , rendering just as 'safe' as any other sideloaded chrome extension.
Edit: I want add, recently built my own Firefox - pulled out all the Pocket shit and tweaked the UI a bit "my way". Was actually not that hard. I'd love to see 20 forks of Firefox trying different things. Also, anyone know what happened to Librefox?
Honestly if chrome introduced bottom url bar and extensions without limitations... I'd switch back. I didn't switch for privacy but because chrome mobile is is clunky as a web app and I use my phone a lot during the day.
Now contrast that with the number of extensions Chrome would break for me with this update. It's a bigger number. Luckily I'm already on FF.
You may want to consider getting involved in the recently announced WebExtensions Community Group in order to discuss your concerns with the future of browser extensions with browser vendors and other extension developers.
http://w3c.org/community/webextensions https://github.com/w3c/webextensions
> Every little userscript would then have to become an own extension. Anyone who wants to do that has to pay $5 to be able to publish an extension.
So this seems like a good way for Google to make money...and to exert more control by moderating the contents of userscripts.
Manifest v3's proposed content blocking is hilariously crippled, that Google can simply start generating random class IDs and there's no way for uBlock origin to block ads anymore.
Now compare that to what Apple charges
Does this mean they're not allowed to write to the DOM? Because if they are allowed to write to the DOM, they can just add a script tag that loads a script from an arbitrary URL.
Also, the example shows a use of fetch. What keeps the script from eval-ing a string from the result of that fetch?
Am I misunderstanding the security model here?
By my understanding, this is still possible. If you dynamically inject a script tag, your code runs in the JS context of the page itself.
On the other hand, the chrome.tabs.executeScript API referred to in this article injects a "content script", which runs in an isolated world and has access to all of the same extension APIs that statically-deployed code does. As I understand it, this is what they're really aiming to prevent: dynamically-loaded code that runs in the extension's privileged context.
There's a section at the end of the design doc that explicitly lists preventing arbitrary code execution in page contexts as a non-goal, at least for now: https://docs.google.com/document/d/1nPu6Wy4LWR66EFLeYInl3Nzz...
> Also, the example shows a use of fetch. What keeps the script from eval-ing a string from the result of that fetch?
As I mentioned in another comment, Manifest V3 bans the use of eval() in extension code. If you inject a script tag into a page, that script may or may not be allowed to call eval(), depending on the page's content security policy.
Thank you, this is extremely helpful for me understanding the security model here, and explains what I was missing.
> Some common violations include: > > * Including a <script> tag that points to a resource that is not within the extension's package
https://developer.chrome.com/docs/webstore/program_policies/...
No they couldn't, because CSP still applies. Even if the extension itself can inject a script element as DOM node, the actual loading of the script's source would still get blocked because it's not being loaded from a trusted source.
What do we use ?
- Blocking webRequest to change CSP to authorize our overlay script to execute
- executeScript: in most case, the script we execute is just inserting a script tag so it would still work in Manifest v3, but with webapps using Service Worker we have to resolve to download the scripts and execute then directly via executeScript, which will not be possible in v3.
Guess we'll have to bundle the overlay engine in the extension, which is much less flexible than what we had until now, but at least it's a possibility.
> - Blocking webRequest to change CSP to authorize our overlay script to execute
I can't exactly say I'm keen on extensions relaxing CSP rules for a site. The approach I'm interested in exploring here is allowing extension resources to bypass CSP restrictions on a given site. IMO a typical extension shouldn't be able to weaken a site's security, but it should be able to load its own images and scripts on the site.
> - executeScript: in most case, the script we execute is just inserting a script tag so it would still work in Manifest v3, but with webapps using Service Worker we have to resolve to download the scripts and execute then directly via executeScript, which will not be possible in v3.
This is not a viable approach in Manifest V3 as reviewers would consider this remote code injection and therefore a violation of the "Additional Requirements for Manifest V3" section of the policy.
https://developer.chrome.com/docs/webstore/program_policies/...
Bundling the overlay engine with the extension sounds like it may do the trick. Just make sure that the engine cannot be used for malicious purposes (e.g. harvesting user data, arbitrary script injection, etc.).
Every decision taken by the browser developers should only keep in mind the requirements of the users. You want to play DRM content? Sure, we will get that certification but also provide extension APIs that let you save the stream to your disk.
You want to block ads? Sure we will let you load an extension that will do that. No store, no signing, no crap.
... That browser is Chrome. Chrome's massive install base means it is the browser of choice for people who need a coddling browser.
Much as with Windows becoming the dominant operating system resulting in Microsoft having to deal with botnets fabricated from thousands of compromised machines via forced security updates, the dominant system becomes heavily incentivized to protect the least capable users from their own bad decisions.
"Hey, it looks like this extension is doing inappropriate things with your passwords. Would you like to uninstall it?"
The problem with the v2 manifest `chrome.tabs.executeScript` API is that it allows any extension that uses that API to become an undocumented password exfiltrator without any changes to the Chrome extension itself. The new API in manifest v3, in contrast, requires that if, say, my clock extension suddenly became a keylogger, the script that did that would show up in the extension.
The API change is to make it possible for Google to have any hope of vetting extensions in the Chrome Web Store by controlling how their behavior can mutate after Google has signed off on them for inclusion in the store.
That means they will not get the right certification for DRM. The main reason behind them is to prevent saving the stream.
Also, can't executed function just add `<script>` tag with given `src`?
> In addition, MV3 disallows certain CSP modifications for extension_pages that were permitted in MV2. The script-src, object-src, and worker-src directives may only have the following values: self; none; Any localhost source, (http://localhost, http://127.0.0.1, or any port on those domains)
In other words, scripts with access to the extension APIs are no longer allowed to specify the "unsafe-eval" CSP, and so they can no longer call eval().
[1]: https://docs.google.com/document/d/1nPu6Wy4LWR66EFLeYInl3Nzz...
[2]: https://developer.chrome.com/docs/extensions/mv3/intro/mv3-m...
I have a script that would read out the page (TTS) and save the passages it reads to a log, for now it is a bookmarklet.
For your case, you'll probably want to save the bookmarklet as a JS file, let's say content.js, and inject in when you click the extension's icon. Here's the basics to get you started.
manifest.json
{
"name": "Demo",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting",
"activeTab"
],
"background": {
"service_worker": "background.js"
},
"action": {}
}
background.js chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: {tabId: tab.id},
files: ['content.js'],
});
});
content.js alert('It worked!');And yet the situation could happen again today without anyone being the wiser for months.
Specifically, we wanted to add support for dynamic content scripts and to expand the capabilities of the executeScript method.So the extension itself is basically a bundle of web resources like HTML, CSS, and JS files. Today, the only way an extension can ask Chrome to automatically inject a content script on a page is to declare what scripts should be injected on which sites in the extension's manifest. For example…
"content_scripts": [
{
"matches": ["*://*.nytimes.com/*"],
"js": ["content-script.js"],
"run_at": ["document_start"]
}
],
This snippet from a manifest file will inject a file in the extensin's bundle called "content-script.js" onto all New York Times web pages the user visits right as the page start loading. The downside to this approach is that this is a static declaration; after the extension is installed it can't say "hey Chrome, I also you want you to inject that same script on BBC websites.In the quote you highlighted, what I was trying to say was that we are also planning to give extensions the ability to modify the set of content scripts while the extension is running. This means the extension will be able to ask Chrome to automatically inject the same script on BBC websites.
What's the difference between chrome.scripting and a content script that you pass messages to?
Once the content script is loaded, AFAIK its execution behaves the same no matter how it was loaded.