diff --git a/README.md b/README.md index 53886788..b5fc3f43 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,9 @@ Changes to patches are licensed according to the header in the files this patch [Phoenix](https://phoenix.celenity.dev/) is licensed under the [GNU General Public License, version 3 or later](https://phoenix.celenity.dev/LICENSE). -`tor-spoof-english.patch` is taken from the [Tor Project](https://support.torproject.org/about/distribute-tor/). See [LICENSE](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/LICENSE). +`librewolf-rs-blocker.patch` is adapted from [LibreWolf](https://librewolf.net/). See [LibreWolf License and Disclaimers](https://librewolf.net/license-disclaimers/). + +`tor-spoof-english.patch` is adapted from the [Tor Project](hhttps://www.torproject.org/). See [LICENSE](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/LICENSE). ## Notices diff --git a/patches/librewolf-rs-blocker.patch b/patches/librewolf-rs-blocker.patch new file mode 100644 index 00000000..478ccfc3 --- /dev/null +++ b/patches/librewolf-rs-blocker.patch @@ -0,0 +1,170 @@ +diff --git a/services/settings/RemoteSettingsClient.sys.mjs b/services/settings/RemoteSettingsClient.sys.mjs +index 32dcdd45d8..fc1e8b0de1 100644 +--- a/services/settings/RemoteSettingsClient.sys.mjs ++++ b/services/settings/RemoteSettingsClient.sys.mjs +@@ -228,6 +228,11 @@ + * @see Downloader.download + */ + async download(record, options) { ++ if (!lazy.Utils.isCollectionAllowed(this.bucketName, this.collectionName)) { ++ throw Error( ++ `Download attempt to RS collection "${this.identifier}" was blocked.` ++ ); ++ } + try { + // Explicitly await here to ensure we catch a network error. + return await super.download(record, options); +@@ -620,6 +625,10 @@ + return; + } + ++ if (!lazy.Utils.isCollectionAllowed(this.bucketName, this.collectionName)) { ++ return; ++ } ++ + // We want to know which timestamp we are expected to obtain in order to leverage + // cache busting. We don't provide ETag because we don't want a 304. + const { changes } = await lazy.Utils.fetchLatestChanges( +@@ -981,6 +990,14 @@ + * Import the JSON files from services/settings/dump into the local DB. + */ + async _importJSONDump() { ++ if ( ++ !lazy.Utils.isCollectionAllowedFromDump( ++ this.bucketName, ++ this.collectionName ++ ) ++ ) { ++ return 0; ++ } + lazy.console.info(`${this.identifier} try to restore dump`); + const result = await lazy.RemoteSettingsWorker.importJSONDump( + this.bucketName, +diff --git a/services/settings/Utils.sys.mjs b/services/settings/Utils.sys.mjs +index d3643aedf2..d3d7127dbf 100644 +--- a/services/settings/Utils.sys.mjs ++++ b/services/settings/Utils.sys.mjs +@@ -75,6 +75,18 @@ + return false; + }); + ++ChromeUtils.defineLazyGetter(lazy, "allowedCollections", () => ++ Services.prefs ++ .getStringPref("browser.ironfox.services.settings.allowedCollections", "") ++ .split(",") ++); ++ ++ChromeUtils.defineLazyGetter(lazy, "allowedCollectionsFromDump", () => ++ Services.prefs ++ .getStringPref("browser.ironfox.services.settings.allowedCollectionsFromDump", "") ++ .split(",") ++); ++ + XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "gServerURL", +@@ -206,11 +218,79 @@ + }, + + /** ++ * Internal code to determine whether the bucket and collection are allowed to ++ * be loaded by the remote settings client for a given list of allowed ++ * bucket/collection combinations. ++ * @param {string} bucket ++ * @param {string} collection ++ * @param {Array} allowedCollections ++ * @returns {boolean} whether the bucket and collection are allowed to load ++ */ ++ _isCollectionAllowedInternal(bucket, collection, allowedCollections) { ++ bucket = this.actualBucketName(bucket); ++ return ( ++ allowedCollections.includes(`${bucket}/${collection}`) || ++ allowedCollections.includes(`${bucket}/*`) || ++ allowedCollections.includes("*") ++ ); ++ }, ++ ++ /** ++ * Determines whether the bucket and collection are allowed to be loaded by the ++ * remote settings client. ++ * @param {string} bucket ++ * @param {string} collection ++ * @returns {boolean} whether the bucket and collection are allowed to load ++ */ ++ isCollectionAllowed(bucket, collection) { ++ if ( ++ this._isCollectionAllowedInternal( ++ bucket, ++ collection, ++ lazy.allowedCollections ++ ) ++ ) { ++ return true; ++ } ++ console.warn( ++ `Connection attempt to RS collection "${bucket}/${collection}" was blocked/filtered.` ++ ); ++ return false; ++ }, ++ ++ /** ++ * Determines whether the bucket and collection are allowed to be loaded from ++ * an in-tree remote settings dump. ++ * @param {string} bucket ++ * @param {string} collection ++ * @returns {boolean} whether the bucket and collection are allowed to load ++ */ ++ isCollectionAllowedFromDump(bucket, collection) { ++ if ( ++ this._isCollectionAllowedInternal( ++ bucket, ++ collection, ++ lazy.allowedCollectionsFromDump ++ ) || ++ this._isCollectionAllowedInternal( ++ bucket, ++ collection, ++ lazy.allowedCollections ++ ) ++ ) { ++ return true; ++ } ++ console.warn( ++ `Access attempt to RS collection "${bucket}/${collection}" from local dump was blocked/filtered.` ++ ); ++ return false; ++ }, ++ ++ /** + * A wrapper around `ServiceRequest` that behaves like `fetch()`. + * + * Use this in order to leverage the `beConservative` flag, for + * example to avoid using HTTP3 to fetch critical data. +- * + * @param input a resource + * @param init request options + * @returns a Response object +@@ -483,7 +563,9 @@ + } + + return { +- changes, ++ changes: changes.filter(change => ++ this.isCollectionAllowed(change.bucket, change.collection) ++ ), + currentEtag: `"${timestamp}"`, + serverTimeMillis, + backoffSeconds, +diff --git a/toolkit/mozapps/extensions/AddonManager.sys.mjs b/toolkit/mozapps/extensions/AddonManager.sys.mjs +index 044e2960be..8837020d49 100644 +--- a/toolkit/mozapps/extensions/AddonManager.sys.mjs ++++ b/toolkit/mozapps/extensions/AddonManager.sys.mjs +@@ -4585,8 +4585,6 @@ AMRemoteSettings = { + */ + RS_ENTRIES_MAP: { + installTriggerDeprecation: [ +- "extensions.InstallTriggerImpl.enabled", +- "extensions.InstallTrigger.enabled", + ], + quarantinedDomains: ["extensions.quarantinedDomains.list"], + }, diff --git a/patches/preferences/ironfox.js b/patches/preferences/ironfox.js index 2e5a64f9..5e0cf818 100644 --- a/patches/preferences/ironfox.js +++ b/patches/preferences/ironfox.js @@ -26,6 +26,10 @@ pref("signon.rememberSignons", true); // [DEFAULT] // We're now blocking this by default with uBlock Origin pref("webgl.disabled", false); // [DEFAULT] +/// Restrict Remote Settings +pref("browser.ironfox.services.settings.allowedCollections", "blocklists/addons,blocklists/addons-bloomfilters,blocklists/gfx,main/addons-manager-settings,main/anti-tracking-url-decoration,main/bounce-tracking-protection-exceptions,main/cookie-banner-rules-list,main/fingerprinting-protection-overrides,main/moz-essential-domain-fallbacks,main/partitioning-exempt-urls,main/password-recipes,main/query-stripping,main/remote-permissions,main/tracking-protection-lists,main/third-party-cookie-blocking-exempt-urls,main/translations-models,main/translations-wasm,main/url-classifier-exceptions,main/url-classifier-skip-urls,main/url-parser-default-unknown-schemes-interventions,security-state/cert-revocations,security-state/ct-logs,security-state/intermediates,security-state/onecrl"); +pref("browser.ironfox.services.settings.allowedCollectionsFromDump", "main/ironfox-fingerprinting-protection-overrides,blocklists/addons,blocklists/addons-bloomfilters,blocklists/gfx,main/anti-tracking-url-decoration,main/cookie-banner-rules-list,main/moz-essential-domain-fallbacks,main/password-recipes,main/remote-permissions,main/translations-models,main/translations-wasm,main/url-classifier-skip-urls,main/url-parser-default-unknown-schemes-interventions,security-state/intermediates,security-state/onecrl"); + /// Set light/dark mode to match system // We still enable light mode by default, just via a patch for Fenix's UI settings instead pref("layout.css.prefers-color-scheme.content-override", 2); // [DEFAULT] diff --git a/scripts/patches.yaml b/scripts/patches.yaml index 364f4b88..627b3c7d 100644 --- a/scripts/patches.yaml +++ b/scripts/patches.yaml @@ -207,6 +207,13 @@ patches: reason: "To ensure content blocking is available from first launch." effect: "Users get content blocking protection without manual installation." category: "Privacy" + + - file: "librewolf-rs-blocker.patch" + name: "Block Remote Settings" + description: "Restricts Remote Settings to only download specific collections specified in preferences." + reason: "To prevent the download/use of unnecessary and undesired Remote Settings from Mozilla (ex. for experimentation)." + effect: "Network activity is further limited, less data is shared with Mozilla, and the user is put in control of what specifically they want to download from Remote Settings." + category: "Privacy" - file: "remove-default-sites.patch" name: "Remove Default Sites"