CVE-2026-74962
Overview
Background
- `CookieStore` API
- A modern asynchronous DOM interface (
dom/cookiestore/) that lets web content read and write cookies, brokered from the content process to the parent process over IPC. - `CheckContentProcessSecurity`
- A parent-process helper in
CookieStoreParent.cppthat validates whether a given content process is permitted to perform the requested cookie operation. - Site isolation
- Gecko’s security model in which each content process is constrained to a specific origin/site, enforced in the parent so a compromised or misbehaving child cannot access another site’s data.
- Fail-open vs. fail-closed
- A design choice in which an authorization check either grants access (
return true) or denies access (return false) when it cannot complete its validation.
Root Cause Analysis
CheckContentProcessSecurity walks a chain of IPC-managed actors — from ThreadsafeContentParentHandle to ContentParent, then to PNeckoParent, then to PCookieServiceParent — in order to reach the CookieServiceParent that actually enforces per-process cookie access policy. At each step, if the corresponding managed actor could not be resolved (contentParent, neckoParent, or csParent was null), the original code returned true, treating the missing security context as if the check had succeeded. This violated the fail-closed invariant that an authorization decision must never grant access when the data needed to make that decision is unavailable.
The fix changes all three early-exit branches to return false, so an inability to locate the enforcing actor now denies the cookie operation instead of silently permitting it. Because the null-actor states represent a content process without the expected Necko/cookie-service plumbing, denying them closes a path by which such a process could bypass the site-isolation cookie restrictions.
CheckContentProcessSecurity returned “allowed” whenever it could not resolve the actor chain needed to evaluate the request. The fix flips those fallback returns to false, making an unresolvable security context deny access rather than grant it.Attack Path
- Obtain a content process without full plumbing
An attacker operates from a content process whose managed
PNeckoParentorPCookieServiceParentactor is absent or not yet established, so the actor lookup returns null. - Issue a CookieStore request
The content process sends a cookie read/write request over IPC to
CookieStoreParent, triggeringCheckContentProcessSecurity. - Trip the null-actor branch
Because one of
contentParent,neckoParent, orcsParentis null, the original code short-circuits and returnstrue, skipping the per-process cookie enforcement inCookieServiceParent. - Bypass site isolation
The cookie operation proceeds without the site-isolation validation that
CookieServiceParentwould have applied, allowing access outside the process’s permitted scope.
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifdom/cookiestore/CookieStoreParent.cpp |
modified |
Files Changed
dom/cookiestore/CookieStoreParent.cpp
Audit Directions
- Fail-open authorizationAudit security/permission helpers for early
return true(or “allow”) paths taken when a required object, actor, or context is null or missing; such fallbacks should deny by default. - IPC actor-chain resolutionReview parent-process code that walks managed-actor chains (
ContentParent→PNeckoParent→PCookieServiceParentand similar) and confirm every failed lookup results in denial, not a permissive default. - Site-isolation enforcement gapsTrace CookieStore and other cross-process data APIs to ensure the per-process enforcement object (e.g.
CookieServiceParent) is always actually consulted, with no code path that skips it while still allowing the operation.
Patch
diff --git a/dom/cookiestore/CookieStoreParent.cpp b/dom/cookiestore/CookieStoreParent.cpp
index 3fb3498e7ab..c1ea81ad4e9 100644
--- a/dom/cookiestore/CookieStoreParent.cpp
+++ b/dom/cookiestore/CookieStoreParent.cpp
@@ -45,19 +45,19 @@ bool CheckContentProcessSecurity(ThreadsafeContentParentHandle* aParent,
RefPtr<ContentParent> contentParent = aParent->GetContentParent();
if (!contentParent) {
- return true;
+ return false;
}
PNeckoParent* neckoParent =
LoneManagedOrNullAsserts(contentParent->ManagedPNeckoParent());
if (!neckoParent) {
- return true;
+ return false;
}
PCookieServiceParent* csParent =
LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
if (!csParent) {
- return true;
+ return false;
}
auto* cs = static_cast<CookieServiceParent*>(csParent);