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
ComponentCore
Bug ClassUAF
Tracker2052562
Fix commitbfe514f21d25 (firefox) +22/-11
CISA KEVNot listed
CreditedOskar L
Disclosed2026-07-21

Changed Functions

FunctionChangeNotes
if
accessible/ipc/DocAccessibleParent.cpp
modified

Files Changed

  • accessible/ipc/DocAccessibleParent.cpp
diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp
index 41fba965cca..c2958285852 100644
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -188,6 +188,16 @@ mozilla::ipc::IPCResult DocAccessibleParent::ProcessShowEvent(
       // This is the first Accessible, which is the root of the shown subtree.
       root = child;
       rootParent = parent;
+      if (!aComplete) {
+        // This is the first message for a show event split across multiple
+        // messages. Save the show target for subsequent messages and return.
+        mPendingShowChild = accData.ID();
+        mPendingShowParent = accData.ParentID();
+        mPendingShowIndex = accData.IndexInParent();
+        if (!rootParent->IsDoc() && !rootParent->RemoteParent()) {
+          return IPC_FAIL(this, "Attempt to split show with detached root");
+        }
+      }
     }
     // If this show event has been split across multiple messages and this is
     // not the last message, don't attach the shown root to the tree yet.
@@ -202,21 +212,11 @@ mozilla::ipc::IPCResult DocAccessibleParent::ProcessShowEvent(
 
   MOZ_ASSERT(CheckDocTree());
 
-  if (!aComplete && !mPendingShowChild) {
-    // This is the first message for a show event split across multiple
-    // messages. Save the show target for subsequent messages and return.
-    const auto& accData = aNewTree[0];
-    mPendingShowChild = accData.ID();
-    mPendingShowParent = accData.ParentID();
-    mPendingShowIndex = accData.IndexInParent();
-    return IPC_OK();
-  }
   if (!aComplete) {
     // This show event has been split into multiple messages, but this is
-    // neither the first nor the last message. There's nothing more to do here.
+    // not the last message. There's nothing more to do here.
     return IPC_OK();
   }
-  MOZ_ASSERT(aComplete);
   if (mPendingShowChild) {
     // This is the last message for a show event split across multiple
     // messages. Retrieve the saved show target, attach it to the tree and fire
@@ -288,6 +288,8 @@ RemoteAccessible* DocAccessibleParent::CreateAcc(
           "Attempt to move RemoteAccessible which has a pending parent");
       return nullptr;
     }
+    MOZ_RELEASE_ASSERT(newProxy->ChildCount() == 0 || newProxy->IsOuterDoc(),
+                       "Reused RemoteAccessible unexpectedly has children!");
     return newProxy;
   }
 
@@ -341,6 +343,15 @@ bool DocAccessibleParent::AttachChild(RemoteAccessible* aParent,
     return false;
   }
 
+  if (!aParent->IsDoc() && !aParent->RemoteParent() &&
+      aParent->ID() != mPendingShowChild) {
+    MOZ_ASSERT_UNREACHABLE("Attempt to attach child to a detached parent!");
+    return false;
+  }
+
+  MOZ_RELEASE_ASSERT(!mPendingShowChild || aChild->ID() != mPendingShowParent,
+                     "Attempt to attach the pending show's parent as a child!");
+
   if (aParent == aChild) {
     MOZ_ASSERT_UNREACHABLE("Attempt to make an accessible its own child!");
     return false;
Loading diff…