User.js: look at userscripts API: e.g firemonkey

Created on 13 Sep 2019  Â·  35Comments  Â·  Source: arkenfox/user.js

From @EstherMoellman 's post here .. opening as a new issue so I can track it


Hi @Thorin-Oakenpants ,

I would like to introduce you FireMonkey: https://addons.mozilla.org/en-US/firefox/addon/firemonkey
GitHub' support page: https://github.com/erosman/support

It is a Mozilla Public License Version 2.0.
And at AMO' page says: "None of my extensions contain any tracking, advertising or privacy infringement."

The Dev @erosman is very responsive. He was tremendously helpful and patient answering me lot of questions, and solving issues in few hours.

FireMonkey is simple, minimalist, so it may not have fancy stuff. It is a matter of personal choice, some users don't care at all about browser performance, they want tons of images, rings, bells, lights and fancy stuff, or they want everything automatized (even if hurts privacy/security). Well, perhaps FireMonkey wont be for them.
I personally only care about browser performance and add-on functions, so for me the less the better. So I love FireMonkey because is very lightweight, very efficient in terms of browser performance, and uses the new API.

PS: Perhaps https://www.ghacks.net/ will be interested on writing a FireMonkey' article.

Most helpful comment

v1.19
Added Web Install option for greasyfork.org
Added Direct Install option for files loaded into tab for https://greasyfork.org/scripts/*.user.js
& file:///*/*.user.js

All 35 comments

Thank you @Thorin-Oakenpants ! It will be great if you can take a look at FireMonkey, posting your review, and who knows, also adding it to your "recommended add-ons" list.
And if you liked FireMonkey, please, recommend it to Martin, perhaps he can write an article at https://www.ghacks.net/

FireMonkey is far from being perfect, but I do like FireMonkey a lot, and that's the only reason I'm promoting/divulging it. Also, the FireMonkey' Dev (@erosman) was so responsive, and help me so much, that I want to help him.

Thank you @Thorin-Oakenpants for reviewing FireMonkey.
:)

I'm not reviewing Firemonkey .. I'm interested in what advantages / differences the API provides

I'm interested in what advantages / differences the API provides

@Thorin-Oakenpants Generally speaking, content script injected by the extensions have certain privileges for being part of the extension. They also have access to a number of WebExtension APIs.

Before Firefox Quantum, user-scripts were injected differently and could be sandboxed but that option was not feasible in Firefox Quantum. When Firefox Quantum was going to be released, I personally brought up this issue that the above set-up is insecure if used for user-scripts and it was decided to create a secure & sandboxed API for user scripts. I also liaised with Luca who was creating the API.

It was Firefox 65 when the API became available and Firefox 68 that the API was officially launched.

The main difference is that the user-scripts injected via userScripts API have no extra privileged and have no access to any extension API.
That is how any page-script in any website is and that is how it should be for better security & privacy.

However, an extension can create special functions to give userscripts additional functionality which are traditionally the GM_/GM. functions.

So the benefit of the API is primary security (and privacy) and then better performance using dedicated API.
The benefit of the extension code is something that has to be judged by the reviewer.

There are some differences and I have tried to document them in the included Help.
TBH, I initially made FireMonkey for my own use and it was much later that I decided to release it. FireMonkey is still in its early days and continues to be developed, taking into account users' feedback.

It was created not as another GM, TM, or VM but a new type of manager. Therefore it's behaviour is not identical to the aforementioned.

It was created not as another GM, TM, or VM but a new type of manger

Yup, I get that :) I just need to analyze the pros (and cons if any). There's a fair bit of quirks between GM, VM and TM over some things (like run @ doc start, running if you block JS on the page, etc), and something that is built into the core (API) can be a better solution (although I'm not sure what the threat model is if you disable JS). Hopefully I'll get to this ticket before Xmas

like run @ doc start

There is already a difference between GM, TM, & VM. I chose document-idle since the Firefox API's default is document-idle.
run-at default behaviour:

GreaseMonkey        document-end
ViolentMonkey       document-end

FireMonkey          document-idle
TamperMonkey        document-idle

running if you block JS on the page

The code injected via the API 'should' be in a different context than the page JS. Blocking JS should only block the page JS and not the JS injected by an extension via API.

Hi @Thorin-Oakenpants ,

It may not be of your interest, but as a simple-average-user of FireMonkey, and after having used Stylus/VM/GM for a long time, I can confirm that FireMonkey has less negative impact on browser resources, while improving overall performance.

Before moving my stuff into FireMonkey, I did tests for more than 2 weeks and with 50 users, using several online and offline tools, and FireMonkey in this field was a winner. Even to my surprise, some CSS' scripts performed better in FireMonkey than in userContent.css. I shared my results with a FF' Engineer.

v1.19
Added Web Install option for greasyfork.org
Added Direct Install option for files loaded into tab for https://greasyfork.org/scripts/*.user.js
& file:///*/*.user.js

It may not be of your interest, but ... Stylus/VM/GM

I consider anything to do with Stylus as not in this ticket: I use half a dozen custom scripts styles plus github-dark ... also because RFP spoofs prefers-color-scheme as light

And, I am interested. I run 4 scripts: two don't matter if JS is disabled on the page (because it requires JS to detect what I am blocking), but the other two do.

v1.19

Sweet. The longer I wait, the more mature it will become: not just the extension, but also the API / firefox bugs

Hi @Thorin-Oakenpants , besides GitHubDark, please do you mind sharing with me your "half a dozen scripts"? I consider you an expert with deep knowledge, and if you allow me, please I would like to take this opportunity "to steal" useful stuff from your scripts.

They're just styles for a few common sites I use to make them dark (I hate all the dark shit out there, they're too dark, I call my shit dark pastel); I haven't updated them for years. I also use them to reduce the wasted space and large font sizes which at the time was becoming way too popular due to mobile. I used to have about 50 of them: I'm down to 8

Example:
example

Example2
example2

@erosman

I wanted to familiarize myself a bit with the new Userscripts API and Firemonkey seemed like a perfect fit to study given that it's lightweight, no-nonsense, purist (no libraries 👍 ) goodstuff :)

Even though I ended up removing a good portion of the code for my personal use because I just don't need it, I really like your extension. Writing your own highlighter is impressive to say the least!

Some things I find questionable, unnecessary or even potentially risky, like for example giving content scripts access to the storage and the whole header thing with fetch and XHR.
It's obvious that you put a lot of work and research into the header part but I just don't know if that's foolproof enough.
IDK if you're aware but extensions can unfortunately uniquely identify a user under certain circumstances. I didn't test if Firemonkey is vulnerable to that but I assume it is or it can be if done wrong.
Yeah, IDK, just my 2 cents from a security/privacy perspective :)

Another problem is that browser.runtime.getBackgroundPage() doesn't work in private windows and if someone's using PB-only mode or probably even just trying to add a new script while in a private window or something like that, Firemonkey is probably completely unusable because of that.

ps: it would be really nice if you'd put the source code up on github. I saw your arguments against it but I still think it could help with fe people providing localization etc and just in general for seeing what kind of changes you make etc. Maybe something to reconsider

Thanks for creating and publishing Firemonkey and keep up the great work! 👍

@earthlng Thank you for your kind comments

Some things I find questionable, unnecessary or even potentially risky, like for example giving content scripts access to the storage

User-scripts don't have direct access to storage. The interaction is screened and limited/controlled via script API.

whole header thing with fetch and XHR

The forbidden headers are removed by the script API so user-scripts have limited/controlled access.

IDK if you're aware but extensions can unfortunately uniquely identify a user under certain circumstances. I didn't test if Firemonkey is vulnerable to that but I assume it is or it can be if done wrong.

That should not apply here. While extension can identify users, user-scripts are in a different scope (content scope vs browser scope).

Another problem is that browser.runtime.getBackgroundPage() doesn't work in private windows and if someone's using PB-only mode or probably even just trying to add a new script while in a private window or something like that, Firemonkey is probably completely unusable because of that.

I didnt know.... I have to test it out.

ps: it would be really nice if you'd put the source code up on github. I saw your arguments against it but I still think it could help with fe people providing localization etc and just in general for seeing what kind of changes you make etc. Maybe something to reconsider

I rewrite code frequently and having to update github every time I make changes is really impractical. Furthermore, while it can be beneficial to get feed back on the code with suggestions for improvements by interested users, my personal experience has shown that it can also lead to unnecessary (sometimes heated) arguments when there are differing views, or even resentment when suggestions are not approved.

User-scripts don't have direct access to storage. The interaction is screened and limited/controlled via script API.

oh right, I didn't see that you're limiting storage access to a subkey of a particular userscript. sorry, my bad.

That should not apply here. While extension can identify users, user-scripts are in a different scope (content scope vs browser scope).

it does apply because with the GM functions it's ultimately the background script that makes the requests. I just tested it and was able to leak the unique extension UUID in the origin header.

They were close to landing a patch for this problem and I've looked at their test file and found this:

We purposefully don't add any host permission for example.org (or all_urls). This ensures the requests below use CORS, which would normally send an Origin header with a moz-extension: scheme.

note the "or all_urls". At first I tested with a normal GET request for both fetch and XHR and for some reason it didn't leak the UUID. I'm not sure if that's because of some of my user.js settings or if it's indeed because you're using the <all_urls> permission and that perhaps prevents GET requests from leaking.
But if you test with a userscript that makes a GM fetch or XHR request using POST for example, you can see the leak in the Network monitor.

I rewrite code frequently and having to update github every time I make changes is really impractical. ...

I totally understand. nvm

it does apply because with the GM functions it's ultimately the background script that makes the requests. I just tested it and was able to leak the unique extension UUID in the origin header.

I tested FireMonkey GM.xmlHttpRequest and don't see any leakage.

Example of POST Headers:

Host: uploaded.net
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: */*
Accept-Language: en,en-US;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
Content-Length: 53
DNT: 1
Connection: keep-alive

Damn, sorry. After I was able to leak with fetch I didn't test XHR anymore and just assumed that it was equally affected based on what they wrote in that bugzilla. This definitely leaks:

(async () => {
  'use strict';
  const response = await GM.fetch('http://nonexistingdomain.org/test', {method: 'POST'});
})();

just match on any domain to test and see the leakage

@erosman

a few typos in options.html:

  • FireMoneky (3x)
  • GreaseMoneky (2x)
  • respose
  • defualt
  • simialr
  • UserScritps
  • GM_fetcht

a few typos in options.html

Ooops ... Thanks :+1:

I was able to leak with fetch

I will test it

Update:
I see.... it seems to be an oversight/bug in fetch API in general (only for POST, not GET). I will discuss it with Mozilla.
_I can remove it manually... let me think about it._

Example:

Host: uploaded.net
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: */*
Accept-Language: en,en-US;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: moz-extension://01c9c042-abd0-4f97-9711-ef2******
DNT: 1
Connection: keep-alive
Content-Length: 0

v1.20 (_to be released_) FireMonkey removes any header that includes 'moz-extension://'

fetch POST now doesn't have any
Origin: moz-extension://01c9c042-abd0-4f97-9711-ef2******

Evaluated Firemonkey for a month and I believe its current state is far from being ready to replace Violentmonkey both in terms of functionality and usability. Actually I’m typing this message after another “aggrrrhh”-like frustration caused by inability to integrate userscript as is (example) without editing.

@erosman, here lies the crux of immature development: at first Firemonkey throws errors related to include/exclude/match parsing (see screenshot below), which are not errors at all with GM/TM/VM (but limitation of Firemonkey’s parser), and when “errors” are resolved (by removing excludes in this case), the script silently fails to work (because unsafe method is not supported, but no popup about that).

![1]

By the way, Greasemonkey still supports unsafeWindow, there is just a warning against using it regularly with the clause “sometimes, you just can’t get around using unsafeWindow”, which seems to be justified in case of the adblocking script (as some ads happen to be tricky to catch).

cc: @ameshkov (Consider using alternatives of unsafeWindow in AdGuard Extra linked in this message.)

@erosman, rewriting popular scripts to make them work with Firemonkey is not justified by “it is different”, yet it is actively promoted as some kind of lightweight alternative. Its UI is not sleek as Violentmonkey’s one, its JS support is underdeveloped, so who cares about performance, especially without proper comparison data?

@sergeevabc take this conversation elsewhere, thank you - you know, like the extension's support pages

@Thorin-Oakenpants, actually this conversation was meant for you as a curator of trusted tools.

FWIW, IMO Firemonkey deserves a spot in the "Recommended Addons" wiki.

Thanks @EstherMoellman for bringing it to our attention

@sergeevabc - I understand that, but at the end of the day it is up to end users to make sure their scripts work, as I've already stated - e.g. on the extensions list under VM, and even on the user scripts page under Other. I just feel the conversation got out of hand. erosman is limited by the API and Firemonkey isn't trying to be anything except exactly what it is.

Also, my understanding is that VM, GM are considering or going to incorporate using this API (at least I've seen issue titles with the api named in it) - IDK in what form or as an option per script or what: but they will face the same limitations anyone does, including erosman

@erosman Thanks for your work :)

@earthlng Go ahead and add it. I'll defer to your superior knowledge in this area. Thanks for vetting, esp the UUID leaking!

Once Firemonkey is added to the wiki, what should we do with our two scripts listed on the User Scripts wiki page. Are they good to run in FM?

@Thorin-Oakenpants, recommending underdeveloped tools is not responsible. The very point of curating is to be a filter, to separate the wheat from the chaff. And right now the best option to run userscripts is Violentmonkey, which works fast, looks sleek and supports the most of greasyfork/openjs/gist posted scripts. Otherwise you create not a recommended list, but “I heard of” list.

I'm not an expert in everything - I'll defer to @earthlng . Just look at the extensions wiki page - a whole heap of extensions have problems - that doesn't mean we don't list them, and we even go out of our way to highlight some of these issues / inconsistencies / incompatibility-with-other-extensions. In other words, just because there's a bug/issue, it doesn't mean it's not worthy.

@earthlng v1.20 uploaded. Please feel free to test and look forward to your feedback regarding the fetch leak.

what should we do with our two scripts listed on the User Scripts wiki page. Are they good to run in FM?

running a window.opener script with FM should be identical to what my window.opener extension does.

The other 2 should be updated to stop the leak but I don't remember how that needs to look like. Maybe @kkapsner can help rewrite them?

@earthlng: which leak are you exactly talking about?

@kkapsner the scripts here that can leak the function name

Let me know if I can be of help.

@kkapsner

which leak are you exactly talking about?

I opened a new issue, see https://github.com/ghacksuserjs/ghacks-user.js/issues/860

@erosman, please see https://github.com/ghacksuserjs/ghacks-user.js/issues/860 - any help would be very much appreciated because I really don't know what I'm doing :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Thorin-Oakenpants picture Thorin-Oakenpants  Â·  7Comments

Thorin-Oakenpants picture Thorin-Oakenpants  Â·  3Comments

Thorin-Oakenpants picture Thorin-Oakenpants  Â·  5Comments

zdat picture zdat  Â·  5Comments

Thorin-Oakenpants picture Thorin-Oakenpants  Â·  5Comments