arkenfox / user.js

Firefox privacy, security and anti-tracking: a comprehensive user.js template for configuration and hardening
MIT License
10.01k stars 513 forks source link

A code snippet #185

Closed Theemim closed 7 years ago

Theemim commented 7 years ago

Hi. I appreciate what you are doing. Thank you. This is something I am test driving:

// FIRST: Set starting milestone and create visual feedback that would indicate incompletion
lockPref("_autoconfigMilestone", "1 (First)");
lockPref("browser.display.background_color", "#ff9900");
lockPref("browser.display.document_color_use", 2);

// SECOND: Disable javascript and put into offline mode to reduce risk from incompletion
lockPref("javascript.enabled", false);
var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var originalOfflineState = ioService.offline;
ioService.offline = true;

// Stuff

// LAST-1: Restore original offline state and enable javascript
ioService.offline = originalOfflineState;
lockPref("javascript.enabled", true);

// LAST: Eliminate visual feedback of incompletion and set final milestone
lockPref("browser.display.background_color", "#ffffff");
lockPref("browser.display.document_color_use", 0);
lockPref("_autoconfigMilestone", "100 (Last)");

See anything you like? Have any suggestions?

earthlng commented 7 years ago

Hi @Theemim and thanks for posting something completely new and fresh. 👍 This would run pretty early in the startup, even before loading prefs.js and user.js, and therefore, without knowing what you do in // Stuff, I don't really see its usefulness. Do you use this for Tor Browser? I think even in TBB this wouldn't guarantee that nothing runs before Tor and the browser is fully up and all the addons loaded and stuff. Basically this would run AND finish way too early, no? I guess it really depends on what you do in // Stuff. Care to elaborate?

Theemim commented 7 years ago

I'm doing what you are doing via autoconfig rather than user.js. You noticed that. I'm making pref changes which are nearly identical to yours, so for purposes of discussion here: The Stuff = ghacks-user.js with user_pref changed to lockPref.

I believe lockPref'd settings persist and "override" any pref changes made via prefs.js and user.js. But the browser and/or addons can change a lockPref'd item. So they can override something set that way. Which they can also do for something set via prefs.js and user.js. I haven't tried applying pref changes to TBB via autoconfig or user.js.

Several times I saw Firefox silently abort processing of autoconfig (due to an error) and proceed to startup. Normally that doesn't happen (an exception gets thrown, which you can catch) and what I saw may have been a glitch (in my code). I decided to play it safe and attempt the risk-reduction shown in the snippet. Some of which could be applied via user.js (which seems more likely to silently abort). Assuming the user confirms that their (modified) user.js has no syntax errors and can run to completion (parrot, nudge nudge, say no more) it is probably overkill.

earthlng commented 7 years ago

Oh okay I see.

I believe lockPref'd settings persist and "override" any pref changes made via prefs.js and user.js.

afaik that's correct.

But the browser and/or addons can change a lockPref'd item.

afaik that's incorrect. But it can be easily tested, simply run Services.prefs.setIntPref (or Bool or Char) in a scratchpad or browser console (with devtools.chrome.enabled;true) and see if the pref gets overwritten. Maybe there are other ways to change prefs as well, idk, but this is what most of the code uses anyway.

If you want to make sure nothing runs before the browser is fully up and all addons loaded, etc, you could just disable your network adapter, start FF or TBB, check parrot and enable the network again (and reconnect tor).

it is probably overkill.

yeah I agree. I haven't used autoconfig yet because it applies to all profiles and a user.js is just more convenient IMHO. I don't update my user.js very often anymore but when I do, I only need to check the parrot once and from then on I know that everything was and will be applied correctly all the time.

For our purposes here, locking prefs would be very inconvenient if users want to temporarily change a pref, fe because min.tls.version is set too high for a certain page to load, or whatever.

But I very much appreciate that you brought this up, very refreshing. It also reminded me that you can run and invoke other FF code that way. Pretty cool stuff, thanks 👍

Theemim commented 7 years ago

Normally they wouldn't, but if they want to they can unlockPref() and then make their change. An autoconfig can use pref() instead of lockPref() to allow the user to temporarily override. You can just let it apply to all profiles or you can set different prefs for different profiles, switch on environment variables, prompt for things, etc. But I still agree with you: many would prefer the user.js approach.

I don't know if autoconfig is usable with mobile versions. I also don't know how the shift to WebExtensions, and other planned changes, will impact what can be done in autoconfig (and elsewhere).

Do you mean can't be set via lockPref or have to be set via lockPref? I don't know of any that can't be set and that doesn't make sense to me. I think there are some that have to be set that way or just can't be set via prefs.js or user.js.

Theemim commented 7 years ago

I'll try that in FF54 portable and get back to you.

earthlng commented 7 years ago

balls have zero to me to me to me to me to me to me to me to me to

earthlng commented 7 years ago

Another thing to note is that the cfg's pref() will override user.js

wow, wtf!?! This is so confusing. If you use pref() in mozilla.cfg it acts like user_pref() from user.js (=pref shows as "user set"), but if you use pref() in the user.js it acts like defaultPref() ... ! where is the logic in that??! And the user.js is supposed to be loaded last, then why the hell can it not overwrite pref() or user_pref() configs from any and all previously loaded preferences files?! What I also don't really understand is why it needs a mozilla.cfg at all, if you need to load that from another preferences file anyway? Why not use that directly?!

balls have zero to me to me to me to me to me to me to me to me to

earthlng commented 7 years ago

PS: WebExtensions are locked out of about:config internals

except https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/privacy

earthlng commented 7 years ago

You can just let it apply to all profiles or you can set different prefs for different profiles, switch on environment variables, prompt for things, etc.

Interesting, thanks, I never thought about that. I should play with it sometime. Probably looking at the source code for the WE privacy API and locking all those, wouldn't be a bad idea.

Theemim commented 7 years ago

I took the 2017-07-09 ghacks-user.js. Extracted all lines with string "user_pref". Removed the double slash comment prefixes to make all user_pref calls active. Removed 25 duplicative parrot sets and one duplicative set of urlclassifier.trackingTable. Then I replaced user_pref with lockPref. Result: 593 unique lockPref() sets. Which I put into a FF54 autoconfig file.

Three calls threw exceptions:

lockPref("security.sandbox.content.level", "donotuse");
lockPref("dom.ipc.plugins.sandbox-level.default", "donotuse");
lockPref("dom.ipc.plugins.sandbox-level.flash", "donotuse");

So I changed those illegal values to non-default integer values and tried again. Browser started without error dialogs. I used an extension to extract type and values for those 593 prefs, reading from getBranch(''). Then compared that to what I set. Looks like everything took.

I don't think this proves that there are zero issues using lockPref on any of the prefs in your user.js. There could still be an issue with a certain pref or particular value.

Did that comment about some prefs' values being ignored if changed via prefs.js and user.js ring a bell? I think I read Mozilla was doing something like that to reduce the chances of unexpected tampering with important ones, but I don't remember where I read that. Maybe it is no longer even done.

earthlng commented 7 years ago

Thanks @Theemim! Really glad you found us here, we need more people like you around here ❤️ #nohomo xD

earthlng commented 7 years ago

looking at the source code for the WE privacy API and locking all those, wouldn't be a bad idea.

https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/ext-privacy.js

edit: There also seems to be a 'privacy.services' property which isn't documented just yet

earthlng commented 7 years ago

in my book an APP or system directive should always override a user one

yeah I agree but I don't understand why pref() in cfg doesn't allow a user.js to overwrite it - you can change it in about:config but not from user.js?! why?. Makes no sense to me. If an admin wants to lock prefs that totally makes sense but the other functions/methods are just confusing to me.

I am of course going on the word of @berrythesoftwarecodeprogrammar

I tried it myself today and can confirm what he wrote.

earthlng commented 7 years ago

https://mike.kaply.com/2012/03/16/customizing-firefox-autoconfig-files/ has some more interesting information

crssi commented 7 years ago

@earthlng user.js, that is in profile folder is not processed the last.

earthlng commented 7 years ago

privacy.disable_button.*

check your about:config?filter=disable_button, most (?) [or all??] of these get set automatically. His article is from 2012

earthlng commented 7 years ago

@earthlng user.js, that is in profile folder is not processed the last.

yes I know. I meant in the context of the loading order in regards to "config", as described here: https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/A_brief_guide_to_Mozilla_preferences It should, according to that, be loaded after the config file and the prefs.js. The preferences folder in the profile dir isn't even documented anywhere, afaik.

earthlng commented 7 years ago

autoadmin.refresh_interval is used in downloadAutoConfig(). I'm not sure but I think that this only does a re-download of the autoconfig, and not actually run the autoconfig.

Atavic commented 7 years ago

cfg is touched by admins with tools like this.

Theemim commented 7 years ago

PS: WebExtensions are locked out of about:config internals

That is going to be a problem. Especially for me because I like to compare exports and have been using "legacy" extensions for that. Alright then... bananas! See what you started? I meant Plan B. Which is https://github.com/Theemim/GeckoPrefsExporter. I'm totally open to alternatives though. I know you are diffing things. How are you going about it?

earthlng commented 7 years ago

Wow, that's really cool! When I did my first diffs I also used a custom made legacy addon to export everything from about:config. Now I'm extracting the default preferences files from the 2 omni.ja's and compare those. Both ways have pros and cons. On the pro side I can create diffs for other OSes, I don't have to install or run FF or TBB to get the prefs, don't have to worry about non-printable characters and I also don't get all the timestamp prefs and shit in my outputs. Cons are that I have to manually check the omni.ja's from time to time to make sure I don't miss any split off or newly created preferences files. I also need to open the omnis with a hexeditor from time to time to make sure the loading order of the files has not changed. Fe TBB has added an additional prefs file to one of the omni.ja's and they don't optimize it afterwards and so now the index is not towards the beginning of the file anymore and I'm not sure in which order their default files are loaded. You don't have to worry about all that when you get it from a live "Gecko". You also get all the extensions prefs which is nice and the stats are neat as well. And you can import your output with a spreadsheet program and filter it that way, which is very nice too! gj!! :+1: :+1: double-plus good xD

Theemim commented 7 years ago

I went part of the way down that path, then decided to use live exports. I didn't get as far as you have. I'm not sure I understand how you are creating diffs for other OSes. Could you elaborate on that? Are you just grabbing, or extracting, the omni's for the other OS's? I forget how that all works, now. You gotta write it up for us and put it in the appendix :-) Wait, maybe a video of you doing it would be better? I bet you would make it funny.

Thanks for the thumbs up, I appreciate that.

You have me reading about omni's, and one article mentions optimization fouling up unzippers. I've noticed that system addons don't unzip like xpi's. I wonder if it is related...

earthlng commented 7 years ago

I download the setup for any version + OS from mozilla's ftp and let one of my scripts extract the 2 omni.ja's, and in a 2nd step extract all the preferences files. The file structure in the setups is slightly different for each OS. Based on the setup's filename+ext my script adjusts the path and then just runs a couple of 7zip x(tract) commands, fe.

then extract the preferences files, fe for the main omni.ja for Mac:

7z.exe x temp\Firefox\Firefox.app\Contents\Resources\omni.ja -otemp greprefs.js defaults/pref/marionette.js defaults/pref/services-sync.js

the paths to the omnis are:

Path_WIN = 'core/'
Path_WIN_PAF = 'App/Firefox64/'
Path_MAC = 'Firefox/Firefox.app/Contents/Resources/'
Path_LINUX = 'firefox/'

PAF = portableapps offline setups

earthlng commented 7 years ago

Thanks for the thumbs up, I appreciate that.

dude, double thumbs up! xD you deserve it :+1:

I wonder if it is related...

Probably. Idk if it's because they use an older version of unzip or different versions of optimization.

A few things from my notes from when I went down that road a while ago, may be helpful:


zip -qr9XD omni.ja *

optimizejars.py --deoptimize ./ ./ ./ optimizejars.py --optimize ./ ./ ./

newer file: http://hg.mozilla.org/mozilla-central/file/0874dee6bf42/config/optimizejars.py --> Tue, 06 Sep 2011 12:57:36 -0700

https://blog.mozilla.org/mwu/2010/08/13/omnijar-how-does-it-work/

http://hg.mozilla.org/mozilla-central/file/f7016571b472/config/optimizejars.py

find . | xargs touch -t 201001010000 && zip -r9mX omni.jar $(OMNIJAR_FILES) -x $(NON_OMNIJAR_FILES) && ...


... found that last one in one of the build scripts on DXR

I never managed to get an exact matching copy with mozillas omnis after deopt+reopting, but the optimizejars.py still does a good enough job. There are multiple versions out there, no idea which one they use nowadays, or whether they still use it at all. I did some omni.ja editing for a while but due to the massive changes in each version, patching couldn't reliably be done and I decided wasn't worth the effort. You can easily do a few simple things manually, but anything more than that is just too much work IMO, and I gave up on it.

Edit: I ended up using zip -qr9XD

Theemim commented 7 years ago

Thanks for that followup info @earthlng. I am hoping to revisit some of that and it may prove useful. We're fortunate to have you and your knowledge/skills.

Theemim commented 7 years ago

@Thorin-Oakenpants thank you for the invite. Right now I am trying to figure out how to better align with what you are doing. In the past I just did some processing/diffing to compare the sets your user.js makes to what my autoconfig makes. So I never paid much attention to the structure of your user.js, your work flow, etc. Mind if I ask some questions here?

The latest user.js will always be coded for the latest Firefox Release? So an ESR user would have to work with an earlier copy or make adjustments to your latest? Such as uncommenting deprecated calls that do apply to them and commenting out newer calls that could cause problems?

Theemim commented 7 years ago

I wouldn't know how to leverage Git/GitHub features to make something like this easier. The first thing that popped into my mind was: if every line of interest had an appropriate parsable tag then a tool (perhaps even an end-user one) could adjust the lines for a specific version by adjusting the commenting. I noticed that many lines have (FFXX+) and that would suffice, but not all lines that are FFXX+ have that tag (sometimes it is in the comment preceding). Simple tagging would work best when lines are either in or out. If there are different pref values for different versions it gets messier.

I'm just sharing what I'm thinking. I don't know how well this would work in practice or whether it would be the least amount of work.

Theemim commented 7 years ago

Quick scan for // (something) and deduping produces:

(FF41+)
(FF42-FF50)
(FF49+)
(FF49+) (hidden pref)
(FF50+)
(FF51+)
(FF52+)
(FF53+)
(FF54+)
(FF55+)
(hidden pref)
(hidden pref) (not hidden FF55+)

So there are already some pseudo tags plus possibly others elsewhere in comments. One question is: Say something is marked FF54+. Well FF54 corresponds to ESR 52.2.0 but that doesn't mean the ESR has all the FF54 prefs, does it? ESR was branched from FF52 and only picks up security/important fixes? So it might have some that FF53 and FF54 had, but maybe not?

If so, a FFXX+ tag couldn't apply to both release and ESR. You'd need a tag to indicate when it starts to apply to Release and when it starts to apply to ESR. Then tags to indicate when it no longer applies to each. I think.

Maybe I'm thinking in a different direction than you and what you have in mind is better, but I'm thinking along the lines of a tag or tags that can reflect a range and can be recognized by both software (pattern match) and human. Rough idea:

// (FF55 - TBD)
// (added:FFesr52, removed:FFesr53)

something similar to that.

earthlng commented 7 years ago

That's totally unnecessary. The only differences between FF52.0 + FF52.0 ESR were: plugin.load_flash_only;false // exists only in ESR dom.serviceWorkers.openWindow.enabled // default false in ESR, true in stable javascript.options.wasm // default false in ESR, true in stable

Since FF52.0.0 ESR there were exactly 6 pref changes ESR users just have to re-enable all the deprecated groups for FF53 and newer.

earthlng commented 7 years ago

No, the ones that ESR users still need are those that got deprecated/removed in FF53+: https://github.com/ghacksuserjs/ghacks-user.js/blob/master/user.js#L1888

The ones listed in our 9999 section under FF52 were removed in 52 and also don't exist anymore in 52 ESR: https://github.com/ghacksuserjs/ghacks-user.js/blob/master/user.js#L1861

It doesn't matter if you also re-enable those but it's not really necessary.

To enable a section change /* FFxx to // FFxx.

As of today they only need to change 3 chars to make the user.js ESR-compatible, it doesn't get much easier than that.

earthlng commented 7 years ago

IDK man, I blame that Pants guy. 1 char is possible too:

/* ESR52 still needs all the following prefs
// [NOTE] replace the * with a slash in the line above (// ESR52 ...) to re-enable them if you're using ESR52.x.x
// FF53
...
// FF54
...
// FF55
...
// ***/

we just need to remove the start and end js-comment tags for the FF53+ blocks

crssi commented 7 years ago

Is it a guy now?

earthlng commented 7 years ago

PR: https://github.com/ghacksuserjs/ghacks-user.js/pull/192

crssi commented 7 years ago

Sorry for "it", it wasn't meant personal. ;)

Theemim commented 7 years ago

Cool, that will make things easier for ESR users :+1: You want to close this thread, or leave it open until I have another crazy idea? I'm fine with either.