High firefox UAF 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionSandbox escape due to use-after-free in the Disability Access APIs component
ComponentDOM
Bug ClassUAF
Tracker2016373
Fix commit72320bf4bc0f (firefox) +23/-7
CISA KEVNot listed
CreditedSajeeb Lohani
Disclosed2026-03-24

Changed Functions

FunctionChangeNotes
if
dom/ipc/BrowserBridgeParent.cpp
modified

Files Changed

  • accessible/ipc/DocAccessibleParent.cpp
  • dom/ipc/BrowserBridgeParent.cpp
diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp
index 8d5598edc91..86f71dbb7be 100644
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -889,6 +889,11 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvBindChildDoc(
 ipc::IPCResult DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc,
                                                 uint64_t aParentID,
                                                 bool aCreating) {
+  if (aChildDoc->RemoteParent()) {
+    return IPC_FAIL(this,
+                    "Attempt to add child doc which already has a parent");
+  }
+
   // We do not use GetAccessible here because we want to be sure to not get the
   // document it self.
   ProxyEntry* e = mAccessibles.GetEntry(aParentID);
diff --git a/dom/ipc/BrowserBridgeParent.cpp b/dom/ipc/BrowserBridgeParent.cpp
index 3c92f7a70b7..9497556dc8f 100644
--- a/dom/ipc/BrowserBridgeParent.cpp
+++ b/dom/ipc/BrowserBridgeParent.cpp
@@ -280,10 +280,13 @@ IPCResult BrowserBridgeParent::RecvSetEmbedderAccessible(
 #  if defined(ANDROID)
   MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
 #  endif
-  MOZ_ASSERT(aDoc || mEmbedderAccessibleDoc,
-             "Embedder doc shouldn't be cleared if it wasn't set");
-  MOZ_ASSERT(!mEmbedderAccessibleDoc || !aDoc || mEmbedderAccessibleDoc == aDoc,
-             "Embedder doc shouldn't change from one doc to another");
+  if (!aDoc && !mEmbedderAccessibleDoc) {
+    return IPC_FAIL(this, "Embedder doc shouldn't be cleared if it wasn't set");
+  }
+  if (mEmbedderAccessibleDoc && aDoc && mEmbedderAccessibleDoc != aDoc) {
+    return IPC_FAIL(this,
+                    "Embedder doc shouldn't change from one doc to another");
+  }
   if (!aDoc && mEmbedderAccessibleDoc &&
       !mEmbedderAccessibleDoc->IsShutdown()) {
     // We're clearing the embedder doc, so remove the pending child doc addition
@@ -293,14 +296,22 @@ IPCResult BrowserBridgeParent::RecvSetEmbedderAccessible(
   mEmbedderAccessibleDoc = static_cast<a11y::DocAccessibleParent*>(aDoc);
   mEmbedderAccessibleID = aID;
   if (!aDoc) {
-    MOZ_ASSERT(!aID);
+    if (aID) {
+      return IPC_FAIL(this, "Attempt to clear embedder but id given");
+    }
     return IPC_OK();
   }
-  MOZ_ASSERT(aID);
-  if (GetDocAccessibleParent()) {
+  if (!aID) {
+    return IPC_FAIL(this, "Attempt to set embedder without id");
+  }
+  if (a11y::DocAccessibleParent* embeddedDoc = GetDocAccessibleParent()) {
     // The embedded DocAccessibleParent has already been created. This can
     // happen if, for example, an iframe is hidden and then shown or
     // an iframe is reflowed by layout.
+    if (embeddedDoc->RemoteParent()) {
+      return IPC_FAIL(this,
+                      "Attempt to embed doc which already has an embedder");
+    }
     mEmbedderAccessibleDoc->AddChildDoc(this);
   }
   return IPC_OK();
Loading diff…