Low firefox Logic Error 🔧 Commit mapped

Overview

Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactlow
DescriptionSandbox escape in the Profile Backup component
ComponentCore
Bug ClassLogic Error
Tracker2058093
Fix commitc89eda214d99 (firefox) +19/-20
CISA KEVNot listed
CreditedMozilla
Disclosed2026-09-15

Changed Functions

FunctionChangeNotes
if
browser/components/backup/content/turn-on-scheduled-backups.mjs
modified

Files Changed

  • browser/components/backup/actors/BackupUIChild.sys.mjs
  • browser/components/backup/actors/BackupUIParent.sys.mjs
  • browser/components/backup/content/turn-on-scheduled-backups.mjs
  • browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js
diff --git a/browser/components/backup/actors/BackupUIChild.sys.mjs b/browser/components/backup/actors/BackupUIChild.sys.mjs
index 7a2176eacfc..50f7d5aeabb 100644
--- a/browser/components/backup/actors/BackupUIChild.sys.mjs
+++ b/browser/components/backup/actors/BackupUIChild.sys.mjs
@@ -157,12 +157,9 @@ export class BackupUIChild extends JSWindowActorChild {
       this.sendAsyncMessage("FindBackupsInWellKnownLocations", event.detail);
     } else if (event.type == "BackupUI:ProbeDefaultBackupDir") {
       let targetNodeName = event.composedTarget.nodeName;
-      let parentDirPath = event.detail?.parentDirPath;
       let readAccessGranted = false;
       try {
-        ({ readAccessGranted } = await this.sendQuery("ProbeDefaultBackupDir", {
-          parentDirPath,
-        }));
+        ({ readAccessGranted } = await this.sendQuery("ProbeDefaultBackupDir"));
       } catch (e) {
         lazy.logConsole.error("ProbeDefaultBackupDir failed:", e);
       }
diff --git a/browser/components/backup/actors/BackupUIParent.sys.mjs b/browser/components/backup/actors/BackupUIParent.sys.mjs
index a116c459b17..0c8699d393e 100644
--- a/browser/components/backup/actors/BackupUIParent.sys.mjs
+++ b/browser/components/backup/actors/BackupUIParent.sys.mjs
@@ -270,7 +270,7 @@ export class BackupUIParent extends JSWindowActorParent {
       });
     } else if (message.name == "ProbeDefaultBackupDir") {
       let readAccessGranted = await this.#bs.probeDefaultDirAccess(
-        message.data?.parentDirPath
+        this.#bs.state.embeddedComponentPersistentData?.path || undefined
       );
       return { readAccessGranted };
     } else if (message.name == "PrepareRestoreDialog") {
diff --git a/browser/components/backup/content/turn-on-scheduled-backups.mjs b/browser/components/backup/content/turn-on-scheduled-backups.mjs
index 12e3b06ad1b..0b77f930b0d 100644
--- a/browser/components/backup/content/turn-on-scheduled-backups.mjs
+++ b/browser/components/backup/content/turn-on-scheduled-backups.mjs
@@ -259,19 +259,17 @@ export default class TurnOnScheduledBackups extends MozLitElement {
       detail.password = this._inputPassValue;
     }
 
-    if (this.embeddedFxBackupOptIn && this.backupIsEncrypted) {
-      if (!detail.password) {
-        this.dispatchEvent(
-          new CustomEvent("SpotlightOnboardingAdvanceScreens", {
-            bubbles: true,
-          })
-        );
-        return;
-      }
-
-      detail.parentDirPath =
-        this.backupServiceState?.embeddedComponentPersistentData?.path ||
-        detail.parentDirPath;
+    if (
+      this.embeddedFxBackupOptIn &&
+      this.backupIsEncrypted &&
+      !detail.password
+    ) {
+      this.dispatchEvent(
+        new CustomEvent("SpotlightOnboardingAdvanceScreens", {
+          bubbles: true,
+        })
+      );
+      return;
     }
 
     this._pendingConfirmDetail = detail;
@@ -279,7 +277,6 @@ export default class TurnOnScheduledBackups extends MozLitElement {
       new CustomEvent("BackupUI:ProbeDefaultBackupDir", {
         bubbles: true,
         composed: true,
-        detail: { parentDirPath: detail.parentDirPath },
       })
     );
   }
diff --git a/browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js b/browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js
index e7bc69ba7af..0254a056254 100644
--- a/browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js
+++ b/browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js
@@ -575,7 +575,7 @@ add_task(async function test_embedded_component_persistent_data_filepicker() {
   await BrowserTestUtils.withNewTab("about:preferences#sync", async browser => {
     await waitInitialRequestStateSettled();
     let sandbox = sinon.createSandbox();
-    sandbox
+    let probeStub = sandbox
       .stub(BackupService.prototype, "probeDefaultDirAccess")
       .resolves(true);
 
@@ -638,6 +638,11 @@ add_task(async function test_embedded_component_persistent_data_filepicker() {
     await promise;
     await settings.updateComplete;
 
+    Assert.ok(
+      probeStub.calledWith(mockCustomParentDir),
+      "probeDefaultDirAccess should be called with the persisted path"
+    );
+
     sandbox.restore();
   });
 
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js b/browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js
index e7bc69ba7af..0254a056254 100644
--- a/browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js
+++ b/browser/components/backup/tests/browser/browser_settings_turn_on_scheduled_backups.js
@@ -575,7 +575,7 @@ add_task(async function test_embedded_component_persistent_data_filepicker() {
   await BrowserTestUtils.withNewTab("about:preferences#sync", async browser => {
     await waitInitialRequestStateSettled();
     let sandbox = sinon.createSandbox();
-    sandbox
+    let probeStub = sandbox
       .stub(BackupService.prototype, "probeDefaultDirAccess")
       .resolves(true);
 
@@ -638,6 +638,11 @@ add_task(async function test_embedded_component_persistent_data_filepicker() {
     await promise;
     await settings.updateComplete;
 
+    Assert.ok(
+      probeStub.calledWith(mockCustomParentDir),
+      "probeDefaultDirAccess should be called with the persisted path"
+    );
+
     sandbox.restore();
   });
Loading diff…