Medium firefox Logic Error 🔧 Commit mapped

Overview

Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionSite isolation issue in the DOM: Navigation component
ComponentDOM
Bug ClassLogic Error
Tracker2049981
Fix commitcd3ea2c86c26 (firefox) +5/-1
CISA KEVNot listed
CreditedYaqoub Aldurayhim
Disclosed2026-07-21

Background

`BrowserParent`
the parent-process actor that manages a single content process’s top-level frame and mediates its IPC messages.
`WindowGlobalParent` (`WGP`)
the parent-process representation of a specific window/document (a global) living in a content process.
`BrowsingContext`
the parent-process object modeling a frame or tab whose subtree ownership determines which process is allowed to host its documents.
Site isolation
the security model that keeps documents of different origins in separate content processes so a compromised process cannot act on another origin’s frames.

Root Cause Analysis

The vulnerable path is BrowserParent::RecvNewWindowGlobal in dom/ipc/BrowserParent.cpp, which handles a content process’s request to register a new WindowGlobalParent for a given browsingContext.

Before the fix, the handler validated only that the target browsingContext belonged to a BrowsingContextGroup known for the child process, but never confirmed that the browsingContext actually lived within this BrowserParent’s frame subtree. This broke the invariant that a content process may only create globals for browsing contexts it legitimately owns — a compromised child could name an arbitrary sibling or unrelated BrowsingContext in the same group.

The fix adds an explicit check: unless the target is this actor’s own mBrowsingContext, its parent WindowGlobalParent must exist and must be managed by this same BrowserParent (parentWgp->Manager() != this), otherwise the message is rejected with IPC_FAIL. This works because it forces the new global to attach only to a parent window already owned by this process, keeping the parent-side frame tree consistent with process ownership.

Key insight
The core mistake was authorizing a cross-process object creation on group membership alone, without verifying subtree ownership; the fix closes it by requiring the target BrowsingContext’s parent window context to be managed by the requesting BrowserParent.

Attack Path

  1. Compromise a content process An attacker gains code execution in a content process (e.g., via a separate renderer bug) so it can forge IPC messages to the parent.
  2. Target a foreign BrowsingContext The process sends RecvNewWindowGlobal naming a BrowsingContext that shares its BrowsingContextGroup but is not in its own frame subtree.
  3. Pass the weak check The pre-fix IsKnownForChildID group check succeeds because the context is merely in the same group.
  4. Register an illegitimate global A WindowGlobalParent is created and attached for a document the process should not host, violating site isolation.

Impact Assessment

An attacker with a compromised content process could induce the parent process to create a WindowGlobalParent for a BrowsingContext outside its ownership, letting one process influence or spoof another origin’s global and undermining cross-origin isolation guarantees. The effect is in the trusted parent process’s model of the frame tree, driven from a content child. The precondition is prior control of a content process capable of sending IPC; the issue is rated moderate/medium with no memory-corruption primitive shown in the diff.

Files Changed

  • dom/ipc/BrowserParent.cpp

Audit Directions

  • IPC ownership validation
    Audit other Recv* handlers that accept a BrowsingContext or context ID from a child and confirm each verifies subtree/process ownership, not just group membership.
  • Group-membership-as-authorization
    Flag any use of IsKnownForChildID or similar group checks as the sole gate on a privileged cross-process operation.
  • Parent/child tree consistency
    Look for places that attach WindowGlobalParent or frame objects without checking that the parent context is managed by the same actor (Manager() == this).
diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp
index 6a6126b3640..ca69f14836c 100644
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -1367,6 +1367,11 @@ IPCResult BrowserParent::RecvNewWindowGlobal(
   if (!browsingContext->Group()->IsKnownForChildID(OtherChildID())) {
     return IPC_FAIL(this, "Invalid BrowsingContextGroup for process");
   }
+  WindowGlobalParent* parentWgp = browsingContext->GetParentWindowContext();
+  if (browsingContext != mBrowsingContext &&
+      (!parentWgp || parentWgp->Manager() != this)) {
+    return IPC_FAIL(this, "BrowsingContext is not in BrowserParent subtree");
+  }
   if (!aInit.principal()) {
     return IPC_FAIL(this, "Cannot create without valid principal");
   }
@@ -1375,7 +1380,6 @@ IPCResult BrowserParent::RecvNewWindowGlobal(
   }
 
   nsCOMPtr<nsIURI> docURI = aInit.documentURI();
-  WindowGlobalParent* parentWgp = browsingContext->GetParentWindowContext();
 
   // Ensure we never load a document with a content principal in
   // the wrong type of webIsolated process
Loading diff…