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
Reviewer notes: Diff is a disabled-by-default feature flag dropping SW-response code cache; it mitigates rather than demonstrates the V8 compiled-code mismatch. Type-confusion/corruption primitive inferred from advisory, not shown in diff.
A second, independent AI reviewer (not a human) re-derived this analysis from the fixing commit and the vendor advisory, looking for errors.
Tracker547815507
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
CreditedJihyeon Jeong (Compsec Lab, Seoul National University / Research Intern)
Reported2026-08-17 (per vendor advisory)
Fix landed2026-09-10 (public git)
Disclosed2026-09-15
Patch gapNot computed: several commits cite this bug and it is not yet established which one is the fix.

Background

Code cache / cached metadata
V8’s serialized compilation artifact (bytecode/compiled code) stored alongside a script’s URL so a later load can skip re-parsing, valid only if the served bytes exactly match the bytes that produced it.
ServiceWorker `respondWith()`
a fetch event handler in a page-controlled ServiceWorker can synthesize or substitute the response for any subresource request, so the bytes a page receives need not be the bytes at the requested URL.
Isolated code cache
the URL-keyed on-disk cache Blink consults for a passthrough response (ShouldUseIsolatedCodeCache, CachedMetadataSender::Create); it assumes the response body corresponds to the cached metadata for that URL.
`ServiceWorkerCodeCache` feature flag
the new RuntimeEnabledFeatures flag added by this patch, disabled by default, that gates whether cached metadata is honored for any response WasFetchedViaServiceWorker().

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: Diff is a disabled-by-default feature flag dropping SW-response code cache; it mitigates rather than demonstrates the V8 compiled-code mismatch. Type-confusion/corruption primitive inferred from advisory, not shown in diff.

When a subresource script was fetched through a ServiceWorker, Blink still attached a URL-keyed cached-metadata handler and consulted the isolated code cache for it, on the assumption that a “passthrough” ServiceWorker response carries the same bytes found at the request URL. A page-controlled ServiceWorker can violate that assumption by returning arbitrary bytes for a URL while cached metadata (V8 compiled code) keyed on that URL persists from a prior, different response, so V8 could deserialize compiled code that does not match the script it is actually compiling — a type confusion.

The patch adds guards in CachedMetadataSender::Create, ShouldUseIsolatedCodeCache, the response-handling path in script_resource.cc, and the streaming path in script_streamer.cc that, whenever ServiceWorkerCodeCacheEnabled() is false (the default) and WasFetchedViaServiceWorker() is true, refuse to create/consult a cache handler and drop any cached metadata. This works because it removes the code-cache path entirely for ServiceWorker-served responses, so no mismatched metadata can ever be handed to V8. The change is a restriction (tightening): it disables a previously-always-on caching path for the ServiceWorker case rather than loosening a check.

Key insight
The single mistake was trusting a ServiceWorker-served response’s URL as a valid key for reusing V8 cached metadata, when the ServiceWorker can decouple the URL from the bytes; the fix bypasses code caching for any WasFetchedViaServiceWorker() response so metadata and bytes can never be mismatched.

Attack Path

  1. Register a controlling ServiceWorker An attacker who controls an origin registers a ServiceWorker with a fetch handler over its in-scope pages (requires a secure context on the attacker’s own origin).
  2. Seed the code cache The ServiceWorker first serves a script at a given URL whose response looks like a passthrough, causing Blink to store URL-keyed cached metadata (V8 compiled code) for it via the isolated code cache path.
  3. Serve mismatched bytes On a later request for the same URL, the ServiceWorker calls respondWith() with different script bytes; the pre-patch ShouldUseIsolatedCodeCache/CachedMetadataSender::Create still supply the stale cached metadata alongside the new source.
  4. Trigger the type confusion V8 deserializes the stale compiled code as if it corresponds to the new source, producing a type confusion in the renderer’s V8 engine.
  5. Escalate (inferred) A controlled V8 type confusion is a classic primitive for corrupting object types and achieving memory read/write and code execution in the renderer; the patch itself only removes the mismatch and does not demonstrate the downstream primitive.

Impact Assessment

An attacker who serves a controlled site with a ServiceWorker gains a V8 type confusion in the renderer process, from ordinary web content with no special privilege beyond hosting the origin and its ServiceWorker. This can plausibly be developed into memory corruption and remote code execution within the sandboxed renderer (inferred), but exploited-in-the-wild status and a severity rating are not established by the patch or provided advisory text. The fix ships disabled-by-default, indicating Chrome chose to turn off ServiceWorker subresource code caching entirely as the mitigation.

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

  • URL-keyed caches over interceptable responses
    Audit every consumer of cached metadata, HTTP cache, or compiled-artifact reuse that keys on a request URL, and confirm it revalidates against ServiceWorker (WasFetchedViaServiceWorker), redirect, and respondWith-substituted bodies before reusing the artifact.
  • Serialized V8 artifacts vs. actual source
    Look for any path that deserializes V8 bytecode/compiled code without a byte-level or hash check tying the artifact to the exact source being compiled, since a type confusion arises whenever the two can diverge.
  • Passthrough assumptions in the loader
    Review other spots that treat a “passthrough” ServiceWorker response as equivalent to a direct network fetch (SetUrlListViaServiceWorker, CacheStorageCacheName handling), as those assumptions can be broken by a ServiceWorker returning arbitrary content for a claimed URL.
From c0b5e81749361a9c8a79990f2c721a16d141882c Mon Sep 17 00:00:00 2001
From: Takashi Nakayama <[email protected]>
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 <[email protected]>
Reviewed-by: Shunya Shishido <[email protected]>
Commit-Queue: Takashi Nakayama <[email protected]>
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.