High patch-now ~ plausible CVSS 8.8 chrome Type Confusion 🔧 Commit mapped

Overview

High
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactType confusion in ServiceWorker
DescriptionType confusion in ServiceWorker
ComponentServiceWorker
Sub-componentServiceWorker
Bug ClassType Confusion
Action tierpatch-now — corruption primitive, web-reachable in default config (plausible) — upheld by independent review by AI
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Independent review by AIPlausible
The mapped commit may not contain the whole fix.
Reviewer notes: Impact says the advisory gives no severity, but it states high. The advisory does not name the renderer process; that is inferred. Otherwise it correctly notes this is a default-off kill switch citing four bugs, with the defect not shown.
A second, independent AI reviewer (not a human) re-derived this analysis from the fixing commit and the vendor advisory, looking for errors.
Tracker558367547
Fix commitc0b5e8174936 (chromium/src) +103/-1
CWECWE-843 (Type confusion)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedCristian Di Nicola (@crih.exe)
Reported2026-09-07 (per vendor advisory)
Fix landed2026-09-10 (public git)
Disclosed2026-09-15
Patch gap5 days — fix public in source before the advisory

Background

V8 code cache (cached metadata)
Serialized V8 compilation data that Blink stores for a script response and later hands back to V8 (for example as cached_metadata during script streaming) so V8 can skip compiling the script again.
Service-worker-mediated subresource
A script request answered by a controlling service worker through respondWith, which ResourceResponse::WasFetchedViaServiceWorker() / head->was_fetched_via_service_worker reports.
Existing SW code-cache routing
Before the patch, the context comments and tests already sent passthrough SW responses (respondWith(fetch(evt.request.url))) to the site-isolated code cache and cache.match responses to the Cache Storage code cache. The tests named DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWith{DifferentURL,SyntheticCache,DifferentURLCache}Response already excluded synthetic and different-URL responses.
`ServiceWorkerCodeCache`
A new runtime-enabled feature in runtime_enabled_features.json5, with no status and so disabled by default (as the commit message says), that gates every V8 code-cache path for SW-mediated subresources.

Root Cause Analysis

Verify before building a PoC

This analysis is consistent with the fixing commit but not fully provable from it: part of the vulnerable path lives in code the fix commit does not touch. Confirm the trigger and the sink against the source before relying on it for exploit development.
What the commit does not establish: Impact says the advisory gives no severity, but it states high. The advisory does not name the renderer process; that is inferred. Otherwise it correctly notes this is a default-off kill switch citing four bugs, with the defect not shown.

This commit only partly matches the advisory: it is a kill-switch mitigation that lists four bugs (558367547, 546413288, 547815507, 558342353), and it does not show the specific defect behind the type confusion. Before the patch, Blink did not code-cache SW responses unconditionally: synthetic and different-URL SW responses were already excluded, and only passthrough responses (site-isolated cache) and cache.match responses (Cache Storage cache) could produce or consume V8 code cache, as the existing tests and the context comment “Non-ServiceWorker scripts and passthrough SW responses use the site isolated code cache” show.

The patch tightens this: with ServiceWorkerCodeCache off by default, any response with WasFetchedViaServiceWorker() set gets a NullCachedMetadataSender, false from ShouldUseIsolatedCodeCache, an early return in ScriptResource right after cached_metadata_handler_ = nullptr (so no handler is created), and a cached_metadata.reset() in script_streamer.cc, placed before the existing WebAssembly MIME check. Each guard runs before metadata is sent or consumed, which removes the whole SW code-cache surface rather than repairing one invariant. The diff therefore does not show which invariant in that path was broken or how it led to a type confusion, and any specific mechanism, such as compiled data being applied to a mismatched script or cache-type confusion, is (inferred).

Key insight
The diff does not show the core defect. It shows that Chromium chose to turn off V8 code caching for all service-worker-mediated subresources by default (ServiceWorkerCodeCache) instead of patching the passthrough and Cache Storage code-cache paths that were still allowed. That fits several related bugs in that code-cache surface, which the commit references.

Attack Path

  1. Control a service worker Any web origin can register a service worker that intercepts its own pages’ subresource script fetches. This is the default web platform, with no special flags.
  2. Serve a still-eligible SW response The worker answers a script request in a way that was still eligible for code caching before the patch, such as a passthrough fetch of the same URL or a cache.match Cache Storage response. Synthetic and different-URL responses were already excluded.
  3. Drive code-cache produce/consume Loading that script makes Blink create a cache handler and sender (ScriptResource, CachedMetadataSender) and pass stored cached_metadata to V8 through script_streamer.cc. These are exactly the paths the patch now cuts off for SW responses.
  4. Trigger the type confusion A defect somewhere in this SW code-cache path causes the “Type confusion in ServiceWorker” the advisory reports. The concrete trigger, the confused types and any memory-corruption primitive are not in the diff (inferred).

Impact Assessment

The advisory reports a type confusion in the renderer process, reachable by web content that controls a service worker on its own origin. The only preconditions are a supported browser configuration and the code-cache path being active, which was the pre-patch default for eligible SW responses. Escalation beyond the type confusion, such as renderer code execution, is (inferred). The vendor advisory rates this high severity and does not report in-the-wild exploitation; NVD scores it CVSS 8.8.

Changed Functions

FunctionChangeNotes
if
third_party/blink/renderer/bindings/core/v8/script_streamer.cc
modified
ServiceWorkerV8CodeCacheForCacheStorageTest
content/browser/service_worker/service_worker_browsertest.cc
modified
ServiceWorkerV8CodeCacheForCacheStorageTest
content/browser/service_worker/service_worker_browsertest.cc
modified
TEST
third_party/blink/renderer/core/loader/resource/script_resource_test.cc
modified

Files Changed

  • third_party/blink/renderer/platform/runtime_enabled_features.json5
  • third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
  • third_party/blink/renderer/bindings/core/v8/script_streamer.cc
  • third_party/blink/renderer/core/loader/resource/script_resource.cc
  • content/browser/service_worker/service_worker_browsertest.cc
  • third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc
  • third_party/blink/renderer/core/loader/resource/script_resource_test.cc

Audit Directions

  • Remaining SW code-cache routes
    The flag is only a mitigation. Review the passthrough-to-isolated-cache and cache.match-to-Cache-Storage routing in cached_metadata_handler.cc, plus the consumers in ScriptResource and script_streamer.cc. Look for cases where stored metadata could be applied to a response or script type other than the one that produced it. These paths come back if ServiceWorkerCodeCache is ever enabled.
  • Kill-switch completeness
    Check every other place that reads or writes V8 code cache for a response, such as module scripts, worker scripts and mojom::blink::CodeCacheType WebAssembly paths, for a WasFetchedViaServiceWorker() check. A consumer the flag misses would leave the surface reachable.
  • Response provenance vs. cache identity
    Wherever a cache entry is chosen by URL or cache name but the bytes come from a service worker or Cache Storage, check that the producer and consumer agree on response identity and script kind before deserializing.
From c0b5e81749361a9c8a79990f2c721a16d141882c Mon Sep 17 00:00:00 2001
From: Takashi Nakayama <tnak@chromium.org>
Date: Thu, 10 Sep 2026 00:32:02 -0700
Subject: [PATCH] ServiceWorker: Add feature flag to disable Code Cache

This CL adds a new runtime enabled feature, `ServiceWorkerCodeCache` to
disable Code Caching for subresource requests through Service Workers.
The new feature is disabled by default.

Bug: 558367547, 546413288, 547815507, 558342353
Change-Id: I2a3b7fbf8c489eec00bce668abb3a7cf438d9f44
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8377021
Reviewed-by: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
Reviewed-by: Shunya Shishido <sisidovski@chromium.org>
Commit-Queue: Takashi Nakayama <tnak@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1695233}
---
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
index aabdaa9e..615c445 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -58,6 +58,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h"
 #include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h"
 #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
@@ -1874,6 +1875,11 @@
     return false;
   }
 
+  if (!RuntimeEnabledFeatures::ServiceWorkerCodeCacheEnabled() &&
+      head->was_fetched_via_service_worker) {
+    cached_metadata.reset();
+  }
+
   if (is_valid_wasm_mime_type) {
     // TODO(https://crbug.com/42204365): Add support for code caching.
     // For now, we clear cached_metadata to avoid unintended side-effects.
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.cc b/third_party/blink/renderer/core/loader/resource/script_resource.cc
index 39a58fe..8b9f1616 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/script_resource.cc
@@ -59,6 +59,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/webui_bundled_cached_metadata_handler.h"
 #include "third_party/blink/renderer/platform/loader/subresource_integrity.h"
 #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
@@ -411,6 +412,10 @@
   }
 
   cached_metadata_handler_ = nullptr;
+  if (response.WasFetchedViaServiceWorker() &&
+      !RuntimeEnabledFeatures::ServiceWorkerCodeCacheEnabled()) {
+    return;
+  }
   // Currently we support the metadata caching only for HTTP family and any
   // schemes defined by SchemeRegistry as requiring a hash check.
   bool http_family = GetResourceRequest().Url().ProtocolIsInHttpFamily() &&
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc
index 3707f3fc..5ef2f37d 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/renderer/platform/loader/fetch/code_cache_host.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -131,6 +132,11 @@
     const ResourceResponse& response,
     mojom::blink::CodeCacheType code_cache_type,
     scoped_refptr<const SecurityOrigin> requestor_origin) {
+  if (!RuntimeEnabledFeatures::ServiceWorkerCodeCacheEnabled() &&
+      response.WasFetchedViaServiceWorker()) {
+    return std::make_unique<NullCachedMetadataSender>();
+  }
+
   // Non-ServiceWorker scripts and passthrough SW responses use the site
   // isolated code cache.
   if (!response.WasFetchedViaServiceWorker() ||
@@ -171,6 +177,11 @@
 bool ShouldUseIsolatedCodeCache(
     mojom::blink::RequestContextType request_context,
     const ResourceResponse& response) {
+  if (!RuntimeEnabledFeatures::ServiceWorkerCodeCacheEnabled() &&
+      response.WasFetchedViaServiceWorker()) {
+    return false;
+  }
+
   // Service worker script has its own code cache.
   if (request_context == mojom::blink::RequestContextType::SERVICE_WORKER)
     return false;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 626e074..85ea1fb 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -5711,6 +5711,10 @@
       status: "experimental",
     },
     {
+      // V8 Code Cache for resource requests passing through Service Worker.
+      name: "ServiceWorkerCodeCache",
+    },
+    {
       // Support for Service Worker APIs in Dedicated Workers.
       // See https://chromestatus.com/feature/6497653025931264
       // See https://issues.chromium.org/issues/40364838
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 42aaa111..01c4800 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -3399,7 +3399,10 @@
 class ServiceWorkerV8CodeCacheForCacheStorageTest
     : public ServiceWorkerBrowserTest {
  public:
-  ServiceWorkerV8CodeCacheForCacheStorageTest() = default;
+  ServiceWorkerV8CodeCacheForCacheStorageTest() {
+    feature_list_.InitAndEnableFeature(
+        blink::features::kServiceWorkerCodeCache);
+  }
 
   ServiceWorkerV8CodeCacheForCacheStorageTest(
       const ServiceWorkerV8CodeCacheForCacheStorageTest&) = delete;
@@ -3474,6 +3477,8 @@
         partition->GetCacheStorageControl(), embedded_test_server()->base_url(),
         std::string("cache_name"), embedded_test_server()->GetURL(kScriptUrl));
   }
+
+  base::test::ScopedFeatureList feature_list_;
 };
 
 const char ServiceWorkerV8CodeCacheForCacheStorageTest::kPageUrl[] =
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource_test.cc b/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
index df582f1..4a1d54b 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
@@ -9,6 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/task_environment.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -323,5 +324,35 @@
   enable_webui_bundled_code_caching(false);
 }
 
+TEST(ScriptResourceTest, ServiceWorkerCodeCacheFlag) {
+  test::TaskEnvironment task_environment;
+  V8TestingScope scope;
+  const KURL url("https://www.example.com/sw-script.js");
+
+  {
+    ScopedServiceWorkerCodeCacheForTest scoped_feature(false);
+    ScriptResource* resource =
+        ScriptResource::CreateForTest(scope.GetIsolate(), url, Utf8Encoding());
+    ResourceResponse response(url);
+    response.SetHttpStatusCode(200);
+    response.SetWasFetchedViaServiceWorker(true);
+
+    resource->ResponseReceived(response);
+    EXPECT_FALSE(resource->CacheHandler());
+  }
+
+  {
+    ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
+    ScriptResource* resource =
+        ScriptResource::CreateForTest(scope.GetIsolate(), url, Utf8Encoding());
+    ResourceResponse response(url);
+    response.SetHttpStatusCode(200);
+    response.SetWasFetchedViaServiceWorker(true);
+
+    resource->ResponseReceived(response);
+    EXPECT_TRUE(resource->CacheHandler());
+  }
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
index ba13a0e..a4320bb 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
@@ -9,12 +9,14 @@
 #include "components/persistent_cache/pending_backend.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
 #include "third_party/blink/public/mojom/loader/code_cache.mojom-blink.h"
 #include "third_party/blink/public/platform/url_conversion.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/renderer/platform/loader/fetch/code_cache_host.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -136,6 +138,7 @@
 TEST(
     CachedMetadataHandlerTest,
     SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithPassThroughResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling respondWith(fetch(evt.request.url));
@@ -151,6 +154,7 @@
 TEST(
     CachedMetadataHandlerTest,
     DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithDifferentURLResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling respondWith(fetch(some_different_url))
@@ -166,6 +170,7 @@
 
 TEST(CachedMetadataHandlerTest,
      SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithCacheResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling respondWith(cache.match(some_url));
@@ -179,9 +184,25 @@
   EXPECT_EQ(1u, mock_disk_cache.CacheStorageCachedURLs().size());
 }
 
+TEST(CachedMetadataHandlerTest,
+     DoesNotSendMetadataToPlatformWhenServiceWorkerCodeCacheDisabled) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(false);
+  MockGeneratedCodeCache mock_disk_cache;
+
+  ResourceResponse response(CreateTestResourceResponse());
+  response.SetWasFetchedViaServiceWorker(true);
+  response.SetUrlListViaServiceWorker({response.CurrentRequestUrl()});
+  response.SetCacheStorageCacheName("dummy");
+
+  SendDataFor(response, &mock_disk_cache);
+  EXPECT_EQ(0u, mock_disk_cache.CachedURLs().size());
+  EXPECT_EQ(0u, mock_disk_cache.CacheStorageCachedURLs().size());
+}
+
 TEST(
     CachedMetadataHandlerTest,
     DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithSyntheticCacheResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling
@@ -198,6 +219,7 @@
 TEST(
     CachedMetadataHandlerTest,
     DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithDifferentURLCacheResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling
@@ -213,5 +235,23 @@
   EXPECT_EQ(0u, mock_disk_cache.CacheStorageCachedURLs().size());
 }
 
+TEST(CachedMetadataHandlerTest,
+     ShouldUseIsolatedCodeCacheRespectsServiceWorkerCodeCacheFlag) {
+  ResourceResponse response(CreateTestResourceResponse());
+  response.SetWasFetchedViaServiceWorker(true);
+  response.SetUrlListViaServiceWorker({response.CurrentRequestUrl()});
+
+  {
+    ScopedServiceWorkerCodeCacheForTest scoped_feature(false);
+    EXPECT_FALSE(ShouldUseIsolatedCodeCache(
+        mojom::blink::RequestContextType::SCRIPT, response));
+  }
+  {
+    ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
+    EXPECT_TRUE(ShouldUseIsolatedCodeCache(
+        mojom::blink::RequestContextType::SCRIPT, response));
+  }
+}
+
 }  // namespace
 }  // namespace blink
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 42aaa111..01c4800 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -3399,7 +3399,10 @@
 class ServiceWorkerV8CodeCacheForCacheStorageTest
     : public ServiceWorkerBrowserTest {
  public:
-  ServiceWorkerV8CodeCacheForCacheStorageTest() = default;
+  ServiceWorkerV8CodeCacheForCacheStorageTest() {
+    feature_list_.InitAndEnableFeature(
+        blink::features::kServiceWorkerCodeCache);
+  }
 
   ServiceWorkerV8CodeCacheForCacheStorageTest(
       const ServiceWorkerV8CodeCacheForCacheStorageTest&) = delete;
@@ -3474,6 +3477,8 @@
         partition->GetCacheStorageControl(), embedded_test_server()->base_url(),
         std::string("cache_name"), embedded_test_server()->GetURL(kScriptUrl));
   }
+
+  base::test::ScopedFeatureList feature_list_;
 };
 
 const char ServiceWorkerV8CodeCacheForCacheStorageTest::kPageUrl[] =
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource_test.cc b/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
index df582f1..4a1d54b 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/script_resource_test.cc
@@ -9,6 +9,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/task_environment.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -323,5 +324,35 @@
   enable_webui_bundled_code_caching(false);
 }
 
+TEST(ScriptResourceTest, ServiceWorkerCodeCacheFlag) {
+  test::TaskEnvironment task_environment;
+  V8TestingScope scope;
+  const KURL url("https://www.example.com/sw-script.js");
+
+  {
+    ScopedServiceWorkerCodeCacheForTest scoped_feature(false);
+    ScriptResource* resource =
+        ScriptResource::CreateForTest(scope.GetIsolate(), url, Utf8Encoding());
+    ResourceResponse response(url);
+    response.SetHttpStatusCode(200);
+    response.SetWasFetchedViaServiceWorker(true);
+
+    resource->ResponseReceived(response);
+    EXPECT_FALSE(resource->CacheHandler());
+  }
+
+  {
+    ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
+    ScriptResource* resource =
+        ScriptResource::CreateForTest(scope.GetIsolate(), url, Utf8Encoding());
+    ResourceResponse response(url);
+    response.SetHttpStatusCode(200);
+    response.SetWasFetchedViaServiceWorker(true);
+
+    resource->ResponseReceived(response);
+    EXPECT_TRUE(resource->CacheHandler());
+  }
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
index ba13a0e..a4320bb 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler_test.cc
@@ -9,12 +9,14 @@
 #include "components/persistent_cache/pending_backend.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
 #include "third_party/blink/public/mojom/loader/code_cache.mojom-blink.h"
 #include "third_party/blink/public/platform/url_conversion.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/renderer/platform/loader/fetch/code_cache_host.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -136,6 +138,7 @@
 TEST(
     CachedMetadataHandlerTest,
     SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithPassThroughResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling respondWith(fetch(evt.request.url));
@@ -151,6 +154,7 @@
 TEST(
     CachedMetadataHandlerTest,
     DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithDifferentURLResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling respondWith(fetch(some_different_url))
@@ -166,6 +170,7 @@
 
 TEST(CachedMetadataHandlerTest,
      SendsMetadataToPlatformWhenFetchedViaServiceWorkerWithCacheResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling respondWith(cache.match(some_url));
@@ -179,9 +184,25 @@
   EXPECT_EQ(1u, mock_disk_cache.CacheStorageCachedURLs().size());
 }
 
+TEST(CachedMetadataHandlerTest,
+     DoesNotSendMetadataToPlatformWhenServiceWorkerCodeCacheDisabled) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(false);
+  MockGeneratedCodeCache mock_disk_cache;
+
+  ResourceResponse response(CreateTestResourceResponse());
+  response.SetWasFetchedViaServiceWorker(true);
+  response.SetUrlListViaServiceWorker({response.CurrentRequestUrl()});
+  response.SetCacheStorageCacheName("dummy");
+
+  SendDataFor(response, &mock_disk_cache);
+  EXPECT_EQ(0u, mock_disk_cache.CachedURLs().size());
+  EXPECT_EQ(0u, mock_disk_cache.CacheStorageCachedURLs().size());
+}
+
 TEST(
     CachedMetadataHandlerTest,
     DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithSyntheticCacheResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling
@@ -198,6 +219,7 @@
 TEST(
     CachedMetadataHandlerTest,
     DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorkerWithDifferentURLCacheResponse) {
+  ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
   MockGeneratedCodeCache mock_disk_cache;
 
   // Equivalent to service worker calling
@@ -213,5 +235,23 @@
   EXPECT_EQ(0u, mock_disk_cache.CacheStorageCachedURLs().size());
 }
 
+TEST(CachedMetadataHandlerTest,
+     ShouldUseIsolatedCodeCacheRespectsServiceWorkerCodeCacheFlag) {
+  ResourceResponse response(CreateTestResourceResponse());
+  response.SetWasFetchedViaServiceWorker(true);
+  response.SetUrlListViaServiceWorker({response.CurrentRequestUrl()});
+
+  {
+    ScopedServiceWorkerCodeCacheForTest scoped_feature(false);
+    EXPECT_FALSE(ShouldUseIsolatedCodeCache(
+        mojom::blink::RequestContextType::SCRIPT, response));
+  }
+  {
+    ScopedServiceWorkerCodeCacheForTest scoped_feature(true);
+    EXPECT_TRUE(ShouldUseIsolatedCodeCache(
+        mojom::blink::RequestContextType::SCRIPT, response));
+  }
+}
+
 }  // namespace
 }  // namespace blink
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.