Low chrome UAF 🔧 Commit mapped

Overview

Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Network
DescriptionUse after free in Network
ComponentNetwork
Bug ClassUAF
Tracker564085088
Fix commitcb7afd9a9776 (chromium/src) +46/-1
CISA KEVNot listed
CreditedFindingz
Disclosed2026-10-06

Changed Functions

FunctionChangeNotes
if
services/network/network_context.cc
modified
TEST_F
services/network/cookie_settings_unittest.cc
modified
TEST_F
services/network/network_context_unittest.cc
modified

Files Changed

  • services/network/cookie_settings_unittest.cc
  • services/network/network_context_unittest.cc
  • services/network/network_context.cc
  • services/network/cookie_settings.cc
From cb7afd9a9776ac9e363be4f36540895d5e5d7764 Mon Sep 17 00:00:00 2001
From: Patrick Meenan <[email protected]>
Date: Thu, 24 Sep 2026 10:36:46 -0700
Subject: [PATCH] Make CreateDeleteCookieOnExitPredicate self-contained

The predicate returned by CreateDeleteCookieOnExitPredicate() can be
evaluated asynchronously after cookie settings have been updated. Own a
snapshot of the cookie settings within the callback so that it does not
depend on the live CookieSettings instance, and handle empty predicates
when clearing session-only trust token data.

Bug: 564085088
Change-Id: I590f33f06cd4175cc84a0710b2e6f62da1170f09
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8436075
Reviewed-by: Tsuyoshi Horo <[email protected]>
Commit-Queue: Patrick Meenan <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1704401}
---
diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc
index 4a1bcba3..b4a7741 100644
--- a/services/network/cookie_settings.cc
+++ b/services/network/cookie_settings.cc
@@ -161,8 +161,16 @@
     }
   }
 
+  // The returned predicate may be evaluated asynchronously on a background
+  // sequence after `this` has been modified or destroyed, so bind an owned
+  // snapshot rather than `this`.
+  auto settings_snapshot = std::make_unique<CookieSettings>();
+  settings_snapshot->set_content_settings(ContentSettingsType::COOKIES,
+                                          settings);
+
   return base::BindRepeating(&CookieSettings::ShouldDeleteCookieOnExit,
-                             base::Unretained(this), std::move(settings));
+                             base::Owned(std::move(settings_snapshot)),
+                             std::move(settings));
 }
 
 bool CookieSettings::ShouldIgnoreSameSiteRestrictions(
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index e65378a2e..4f879d0 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -1409,6 +1409,10 @@
 
   DeleteCookiePredicate cookie_predicate =
       cookie_manager_->cookie_settings().CreateDeleteCookieOnExitPredicate();
+  if (!cookie_predicate) {
+    std::move(callback).Run(false);
+    return;
+  }
 
   auto store_predicate = base::BindRepeating(
       [](DeleteCookiePredicate predicate, const std::string& origin) {
diff --git a/services/network/cookie_settings_unittest.cc b/services/network/cookie_settings_unittest.cc
index 5083b68b..584ab61 100644
--- a/services/network/cookie_settings_unittest.cc
+++ b/services/network/cookie_settings_unittest.cc
@@ -861,6 +861,29 @@
       "foo.com", net::CookieSourceScheme::kNonSecure));
 }
 
+TEST_F(CookieSettingsTest, CreateDeleteCookieOnExitPredicateOwnsSnapshot) {
+  auto settings = std::make_unique<CookieSettings>();
+  settings->set_content_settings(
+      ContentSettingsType::COOKIES,
+      {CreateSetting("https://foo.com", "*", CONTENT_SETTING_SESSION_ONLY)});
+
+  DeleteCookiePredicate predicate =
+      settings->CreateDeleteCookieOnExitPredicate();
+  ASSERT_TRUE(predicate);
+
+  // Replace the live settings so "https://foo.com" is now ALLOW.
+  settings->set_content_settings(
+      ContentSettingsType::COOKIES,
+      {CreateSetting("https://foo.com", "*", CONTENT_SETTING_ALLOW)});
+  EXPECT_TRUE(predicate.Run("foo.com", net::CookieSourceScheme::kSecure));
+
+  // Destroy the original CookieSettings instance entirely; the predicate
+  // must still safely evaluate the snapshot.
+  settings.reset();
+  EXPECT_TRUE(predicate.Run("foo.com", net::CookieSourceScheme::kSecure));
+  EXPECT_FALSE(predicate.Run("other.com", net::CookieSourceScheme::kSecure));
+}
+
 TEST_F(CookieSettingsTest, GetCookieSettingSecureOriginCookiesAllowed) {
   CookieSettings settings;
   settings.set_secure_origin_cookies_allowed_schemes({"chrome"});
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 309599c7..3fa2084 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -9979,6 +9979,16 @@
   EXPECT_TRUE(success);
 }
 
+TEST_F(NetworkContextTest, ClearTrustTokenSessionOnlyDataNoSessionOnlyRules) {
+  std::unique_ptr<NetworkContext> network_context =
+      CreateContextWithParams(CreateNetworkContextParamsForTesting());
+  ASSERT_TRUE(network_context->trust_token_store());
+
+  base::test::TestFuture<bool> future;
+  network_context->ClearTrustTokenSessionOnlyData(future.GetCallback());
+  EXPECT_FALSE(future.Get());
+}
+
 // NotifyExternalCacheHit currently assumes that the cache hits are for
 // resources, so ensure that entries corresponding to subframe navigations don't
 // get updated unexpectedly.
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/services/network/cookie_settings_unittest.cc b/services/network/cookie_settings_unittest.cc
index 5083b68b..584ab61 100644
--- a/services/network/cookie_settings_unittest.cc
+++ b/services/network/cookie_settings_unittest.cc
@@ -861,6 +861,29 @@
       "foo.com", net::CookieSourceScheme::kNonSecure));
 }
 
+TEST_F(CookieSettingsTest, CreateDeleteCookieOnExitPredicateOwnsSnapshot) {
+  auto settings = std::make_unique<CookieSettings>();
+  settings->set_content_settings(
+      ContentSettingsType::COOKIES,
+      {CreateSetting("https://foo.com", "*", CONTENT_SETTING_SESSION_ONLY)});
+
+  DeleteCookiePredicate predicate =
+      settings->CreateDeleteCookieOnExitPredicate();
+  ASSERT_TRUE(predicate);
+
+  // Replace the live settings so "https://foo.com" is now ALLOW.
+  settings->set_content_settings(
+      ContentSettingsType::COOKIES,
+      {CreateSetting("https://foo.com", "*", CONTENT_SETTING_ALLOW)});
+  EXPECT_TRUE(predicate.Run("foo.com", net::CookieSourceScheme::kSecure));
+
+  // Destroy the original CookieSettings instance entirely; the predicate
+  // must still safely evaluate the snapshot.
+  settings.reset();
+  EXPECT_TRUE(predicate.Run("foo.com", net::CookieSourceScheme::kSecure));
+  EXPECT_FALSE(predicate.Run("other.com", net::CookieSourceScheme::kSecure));
+}
+
 TEST_F(CookieSettingsTest, GetCookieSettingSecureOriginCookiesAllowed) {
   CookieSettings settings;
   settings.set_secure_origin_cookies_allowed_schemes({"chrome"});
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 309599c7..3fa2084 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -9979,6 +9979,16 @@
   EXPECT_TRUE(success);
 }
 
+TEST_F(NetworkContextTest, ClearTrustTokenSessionOnlyDataNoSessionOnlyRules) {
+  std::unique_ptr<NetworkContext> network_context =
+      CreateContextWithParams(CreateNetworkContextParamsForTesting());
+  ASSERT_TRUE(network_context->trust_token_store());
+
+  base::test::TestFuture<bool> future;
+  network_context->ClearTrustTokenSessionOnlyData(future.GetCallback());
+  EXPECT_FALSE(future.Get());
+}
+
 // NotifyExternalCacheHit currently assumes that the cache hits are for
 // resources, so ensure that entries corresponding to subframe navigations don't
 // get updated unexpectedly.
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.