High chrome Logic Error 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactImproper resource exposure in CacheStorage
DescriptionImproper resource exposure in CacheStorage
ComponentCacheStorage
Bug ClassLogic Error
Tracker552689418
Fix commit0b4f1821f123 (chromium/src) +108/-6
CISA KEVNot listed
CreditedSalvatore Gulizia (Serotav)
Disclosed2026-09-03

Changed Functions

FunctionChangeNotes
TEST_F
content/browser/worker_host/shared_worker_host_unittest.cc
modified
TEST
net/base/network_isolation_key_unittest.cc
modified

Files Changed

  • content/browser/worker_host/shared_worker_host.cc
  • content/browser/worker_host/shared_worker_host.h
  • content/browser/worker_host/shared_worker_host_unittest.cc
  • net/base/network_isolation_key_unittest.cc
From 0b4f1821f123f397738a9ca6fd9f1666c55f9d45 Mon Sep 17 00:00:00 2001
From: Chris Fredrickson <cfredric@chromium.org>
Date: Mon, 31 Aug 2026 14:44:07 -0700
Subject: [PATCH] Ensure SharedWorkers use distinct code caches based on SiteForCookies

Without partitioning the code cache based on this property of the
SharedWorker, two shared workers with the same StorageKey would share
the code cache, even if one is not supposed to have access to 3P cookies
and the other is.

Fixed: 552689418
Change-Id: Ice36567846bfab93b6242cfc526b0191f992a7ad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8308172
Commit-Queue: Chris Fredrickson <cfredric@chromium.org>
Reviewed-by: Joe Mason <joenotcharles@google.com>
Reviewed-by: mmenke <mmenke@chromium.org>
Reviewed-by: Asami Doi <asamidoi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1689294}
---

diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc
index 851958db..8917db9 100644
--- a/content/browser/worker_host/shared_worker_host.cc
+++ b/content/browser/worker_host/shared_worker_host.cc
@@ -94,6 +94,20 @@
                                 source);
 }
 
+net::IsolationInfo ComputeIsolationInfoWithPartition(
+    const blink::StorageKey& storage_key,
+    net::NetworkIsolationPartition partition) {
+  net::IsolationInfo isolation_info = storage_key.ToPartialNetIsolationInfo();
+  if (partition != net::NetworkIsolationPartition::kGeneral &&
+      !isolation_info.IsEmpty()) {
+    return net::IsolationInfo::Create(
+        isolation_info.request_type(), *isolation_info.top_frame_origin(),
+        *isolation_info.frame_origin(), isolation_info.site_for_cookies(),
+        isolation_info.nonce(), partition);
+  }
+  return isolation_info;
+}
+
 }  // namespace
 
 namespace content {
@@ -971,6 +985,14 @@
   return weak_factory_.GetWeakPtr();
 }
 
+net::NetworkIsolationPartition SharedWorkerHost::GetNetworkIsolationPartition()
+    const {
+  return instance_.same_site_cookies() ==
+                 blink::mojom::SharedWorkerSameSiteCookies::kNone
+             ? net::NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone
+             : net::NetworkIsolationPartition::kGeneral;
+}
+
 net::NetworkIsolationKey SharedWorkerHost::GetNetworkIsolationKey() const {
   // Note: Since shared workers are partitioned by the storage key, we'll use
   // the storage key to create a NIK that matches the current partitioning
@@ -978,15 +1000,15 @@
   // different top-level sites will be able to share the same shared worker, so
   // it doesn't make sense to incorporate the top-level site into the NIK in
   // that case either.
-  return GetWorkerStorageKey()
-      .ToPartialNetIsolationInfo()
+  return ComputeIsolationInfoWithPartition(GetWorkerStorageKey(),
+                                           GetNetworkIsolationPartition())
       .network_isolation_key();
 }
 
 net::NetworkAnonymizationKey SharedWorkerHost::GetNetworkAnonymizationKey()
     const {
-  return GetWorkerStorageKey()
-      .ToPartialNetIsolationInfo()
+  return ComputeIsolationInfoWithPartition(GetWorkerStorageKey(),
+                                           GetNetworkIsolationPartition())
       .network_anonymization_key();
 }
 
diff --git a/content/browser/worker_host/shared_worker_host.h b/content/browser/worker_host/shared_worker_host.h
index 18d345a..3e8ef4a 100644
--- a/content/browser/worker_host/shared_worker_host.h
+++ b/content/browser/worker_host/shared_worker_host.h
@@ -34,6 +34,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "net/base/network_isolation_key.h"
+#include "net/base/network_isolation_partition.h"
 #include "services/device/public/cpp/compute_pressure/buildflags.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/network/public/cpp/cross_origin_embedder_policy.h"
@@ -240,6 +241,8 @@
 
   base::WeakPtr<SharedWorkerHost> AsWeakPtr();
 
+  net::NetworkIsolationPartition GetNetworkIsolationPartition() const;
+
   net::NetworkIsolationKey GetNetworkIsolationKey() const;
 
   net::NetworkAnonymizationKey GetNetworkAnonymizationKey() const;
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc
index 925de9e0..68eb091d 100644
--- a/content/browser/worker_host/shared_worker_host_unittest.cc
+++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -86,6 +86,18 @@
 
   base::WeakPtr<SharedWorkerHost> CreateHostWithExtendedLifetime(
       bool extended_lifetime) {
+    return CreateHostWithParams(blink::mojom::SharedWorkerSameSiteCookies::kAll,
+                                extended_lifetime);
+  }
+
+  base::WeakPtr<SharedWorkerHost> CreateHostWithSameSiteCookies(
+      blink::mojom::SharedWorkerSameSiteCookies same_site_cookies) {
+    return CreateHostWithParams(same_site_cookies, /*extended_lifetime=*/false);
+  }
+
+  base::WeakPtr<SharedWorkerHost> CreateHostWithParams(
+      blink::mojom::SharedWorkerSameSiteCookies same_site_cookies,
+      bool extended_lifetime) {
     blink::StorageKey creator_storage_key =
         blink::StorageKey::CreateFirstParty(url::Origin::Create(kWorkerUrl));
     bool is_opaque_origin_enabled = base::FeatureList::IsEnabled(
@@ -99,7 +111,7 @@
         network::mojom::CredentialsMode::kSameOrigin, "name",
         creator_storage_key, worker_storage_key, renderer_origin,
         blink::mojom::SharedWorkerCreationContextType::kSecure,
-        blink::mojom::SharedWorkerSameSiteCookies::kAll, extended_lifetime);
+        same_site_cookies, extended_lifetime);
     auto host = std::make_unique<SharedWorkerHost>(
         &service_, instance, site_instance_,
         std::vector<network::mojom::ContentSecurityPolicyPtr>(),
@@ -667,4 +679,37 @@
   }
 }
 
+TEST_F(SharedWorkerHostTest, NetworkIsolationPartitionForSameSiteCookies) {
+  base::WeakPtr<SharedWorkerHost> host_all = CreateHostWithSameSiteCookies(
+      blink::mojom::SharedWorkerSameSiteCookies::kAll);
+  base::WeakPtr<SharedWorkerHost> host_none = CreateHostWithSameSiteCookies(
+      blink::mojom::SharedWorkerSameSiteCookies::kNone);
+
+  ASSERT_TRUE(host_all);
+  ASSERT_TRUE(host_none);
+
+  EXPECT_EQ(host_all->GetNetworkIsolationPartition(),
+            net::NetworkIsolationPartition::kGeneral);
+  EXPECT_EQ(host_none->GetNetworkIsolationPartition(),
+            net::NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone);
+
+  EXPECT_EQ(host_all->GetNetworkIsolationKey().GetNetworkIsolationPartition(),
+            net::NetworkIsolationPartition::kGeneral);
+  EXPECT_EQ(host_none->GetNetworkIsolationKey().GetNetworkIsolationPartition(),
+            net::NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone);
+  EXPECT_NE(host_all->GetNetworkIsolationKey(),
+            host_none->GetNetworkIsolationKey());
+  EXPECT_NE(host_all->GetNetworkIsolationKey().ToCacheKeyString(),
+            host_none->GetNetworkIsolationKey().ToCacheKeyString());
+
+  EXPECT_EQ(
+      host_all->GetNetworkAnonymizationKey().network_isolation_partition(),
+      net::NetworkIsolationPartition::kGeneral);
+  EXPECT_EQ(
+      host_none->GetNetworkAnonymizationKey().network_isolation_partition(),
+      net::NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone);
+  EXPECT_NE(host_all->GetNetworkAnonymizationKey(),
+            host_none->GetNetworkAnonymizationKey());
+}
+
 }  // namespace content
diff --git a/net/base/network_isolation_key_unittest.cc b/net/base/network_isolation_key_unittest.cc
index 89131568..d75938a 100644
--- a/net/base/network_isolation_key_unittest.cc
+++ b/net/base/network_isolation_key_unittest.cc
@@ -133,6 +133,24 @@
   EXPECT_TRUE(key4.IsTransient());
 }
 
+TEST(NetworkIsolationKeyTest, SharedWorkerSameSiteCookiesNonePartition) {
+  SchemefulSite site1 = SchemefulSite(GURL("http://a.test/"));
+  SchemefulSite site2 = SchemefulSite(GURL("http://b.test/"));
+
+  NetworkIsolationKey general_key(site1, site2, /*nonce=*/std::nullopt,
+                                  NetworkIsolationPartition::kGeneral);
+
+  NetworkIsolationKey shared_worker_none_key(
+      site1, site2, /*nonce=*/std::nullopt,
+      NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone);
+
+  EXPECT_EQ(NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone,
+            shared_worker_none_key.GetNetworkIsolationPartition());
+  EXPECT_EQ(site1.Serialize() + " " + site2.Serialize() + " 4",
+            shared_worker_none_key.ToCacheKeyString());
+  EXPECT_NE(general_key, shared_worker_none_key);
+}
+
 TEST(NetworkIsolationKeyTest, CreateEmptyWithPartition) {
   NetworkIsolationKey key = NetworkIsolationKey::CreateEmptyWithPartition(
       NetworkIsolationPartition::kDnsOverHttps);
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc
index 925de9e0..68eb091d 100644
--- a/content/browser/worker_host/shared_worker_host_unittest.cc
+++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -86,6 +86,18 @@
 
   base::WeakPtr<SharedWorkerHost> CreateHostWithExtendedLifetime(
       bool extended_lifetime) {
+    return CreateHostWithParams(blink::mojom::SharedWorkerSameSiteCookies::kAll,
+                                extended_lifetime);
+  }
+
+  base::WeakPtr<SharedWorkerHost> CreateHostWithSameSiteCookies(
+      blink::mojom::SharedWorkerSameSiteCookies same_site_cookies) {
+    return CreateHostWithParams(same_site_cookies, /*extended_lifetime=*/false);
+  }
+
+  base::WeakPtr<SharedWorkerHost> CreateHostWithParams(
+      blink::mojom::SharedWorkerSameSiteCookies same_site_cookies,
+      bool extended_lifetime) {
     blink::StorageKey creator_storage_key =
         blink::StorageKey::CreateFirstParty(url::Origin::Create(kWorkerUrl));
     bool is_opaque_origin_enabled = base::FeatureList::IsEnabled(
@@ -99,7 +111,7 @@
         network::mojom::CredentialsMode::kSameOrigin, "name",
         creator_storage_key, worker_storage_key, renderer_origin,
         blink::mojom::SharedWorkerCreationContextType::kSecure,
-        blink::mojom::SharedWorkerSameSiteCookies::kAll, extended_lifetime);
+        same_site_cookies, extended_lifetime);
     auto host = std::make_unique<SharedWorkerHost>(
         &service_, instance, site_instance_,
         std::vector<network::mojom::ContentSecurityPolicyPtr>(),
@@ -667,4 +679,37 @@
   }
 }
 
+TEST_F(SharedWorkerHostTest, NetworkIsolationPartitionForSameSiteCookies) {
+  base::WeakPtr<SharedWorkerHost> host_all = CreateHostWithSameSiteCookies(
+      blink::mojom::SharedWorkerSameSiteCookies::kAll);
+  base::WeakPtr<SharedWorkerHost> host_none = CreateHostWithSameSiteCookies(
+      blink::mojom::SharedWorkerSameSiteCookies::kNone);
+
+  ASSERT_TRUE(host_all);
+  ASSERT_TRUE(host_none);
+
+  EXPECT_EQ(host_all->GetNetworkIsolationPartition(),
+            net::NetworkIsolationPartition::kGeneral);
+  EXPECT_EQ(host_none->GetNetworkIsolationPartition(),
+            net::NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone);
+
+  EXPECT_EQ(host_all->GetNetworkIsolationKey().GetNetworkIsolationPartition(),
+            net::NetworkIsolationPartition::kGeneral);
+  EXPECT_EQ(host_none->GetNetworkIsolationKey().GetNetworkIsolationPartition(),
+            net::NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone);
+  EXPECT_NE(host_all->GetNetworkIsolationKey(),
+            host_none->GetNetworkIsolationKey());
+  EXPECT_NE(host_all->GetNetworkIsolationKey().ToCacheKeyString(),
+            host_none->GetNetworkIsolationKey().ToCacheKeyString());
+
+  EXPECT_EQ(
+      host_all->GetNetworkAnonymizationKey().network_isolation_partition(),
+      net::NetworkIsolationPartition::kGeneral);
+  EXPECT_EQ(
+      host_none->GetNetworkAnonymizationKey().network_isolation_partition(),
+      net::NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone);
+  EXPECT_NE(host_all->GetNetworkAnonymizationKey(),
+            host_none->GetNetworkAnonymizationKey());
+}
+
 }  // namespace content
diff --git a/net/base/network_isolation_key_unittest.cc b/net/base/network_isolation_key_unittest.cc
index 89131568..d75938a 100644
--- a/net/base/network_isolation_key_unittest.cc
+++ b/net/base/network_isolation_key_unittest.cc
@@ -133,6 +133,24 @@
   EXPECT_TRUE(key4.IsTransient());
 }
 
+TEST(NetworkIsolationKeyTest, SharedWorkerSameSiteCookiesNonePartition) {
+  SchemefulSite site1 = SchemefulSite(GURL("http://a.test/"));
+  SchemefulSite site2 = SchemefulSite(GURL("http://b.test/"));
+
+  NetworkIsolationKey general_key(site1, site2, /*nonce=*/std::nullopt,
+                                  NetworkIsolationPartition::kGeneral);
+
+  NetworkIsolationKey shared_worker_none_key(
+      site1, site2, /*nonce=*/std::nullopt,
+      NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone);
+
+  EXPECT_EQ(NetworkIsolationPartition::kSharedWorkerSameSiteCookiesNone,
+            shared_worker_none_key.GetNetworkIsolationPartition());
+  EXPECT_EQ(site1.Serialize() + " " + site2.Serialize() + " 4",
+            shared_worker_none_key.ToCacheKeyString());
+  EXPECT_NE(general_key, shared_worker_none_key);
+}
+
 TEST(NetworkIsolationKeyTest, CreateEmptyWithPartition) {
   NetworkIsolationKey key = NetworkIsolationKey::CreateEmptyWithPartition(
       NetworkIsolationPartition::kDnsOverHttps);
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.