File rs-blocker.patch of Package LibreWolf
diff --git a/services/settings/RemoteSettingsClient.sys.mjs b/services/settings/RemoteSettingsClient.sys.mjs
index fc7f6705da46..a3fdd04f03bc 100644
--- a/services/settings/RemoteSettingsClient.sys.mjs
+++ b/services/settings/RemoteSettingsClient.sys.mjs
@@ -228,6 +228,11 @@ class AttachmentDownloader extends Downloader {
* @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.`
+ );
+ }
await lazy.UptakeTelemetry.report(
TELEMETRY_COMPONENT,
lazy.UptakeTelemetry.STATUS.DOWNLOAD_START,
@@ -652,6 +657,10 @@ export class RemoteSettingsClient extends EventEmitter {
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(
@@ -1031,6 +1040,14 @@ export class RemoteSettingsClient extends EventEmitter {
* 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 cbdf07bcdae1..4e923ff44f33 100644
--- a/services/settings/Utils.sys.mjs
+++ b/services/settings/Utils.sys.mjs
@@ -75,6 +75,18 @@ ChromeUtils.defineLazyGetter(lazy, "allowServerURLOverride", () => {
return false;
});
+ChromeUtils.defineLazyGetter(lazy, "allowedCollections", () =>
+ Services.prefs
+ .getStringPref("librewolf.services.settings.allowedCollections", "")
+ .split(",")
+);
+
+ChromeUtils.defineLazyGetter(lazy, "allowedCollectionsFromDump", () =>
+ Services.prefs
+ .getStringPref("librewolf.services.settings.allowedCollectionsFromDump", "")
+ .split(",")
+);
+
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"gServerURL",
@@ -205,12 +217,80 @@ export var Utils = {
return false;
},
+ /**
+ * 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<string>} 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 @@ export var Utils = {
}
return {
- changes,
+ changes: changes.filter(change =>
+ this.isCollectionAllowed(change.bucket, change.collection)
+ ),
currentEtag: `"${timestamp}"`,
serverTimeMillis,
backoffSeconds,