Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactRace in Shared Storage
DescriptionRace in Shared Storage
ComponentShared Storage
Bug ClassRace
Tracker496380960
Fix commit782c8de9ff11 (chromium/src) +11/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-05

Changed Functions

FunctionChangeNotes
if
content/browser/shared_storage/shared_storage_worklet_host.cc
modified

Files Changed

  • content/browser/shared_storage/shared_storage_worklet_host.cc
From 782c8de9ff11930c48bd51c823516d0fa4703c82 Mon Sep 17 00:00:00 2001
From: Camillia Smith Barnes <[email protected]>
Date: Fri, 03 Apr 2026 14:31:32 -0700
Subject: [PATCH] Shared Storage: Enforce data origin opt-in in SharedStorageWorkletHost

When a SharedStorage worklet requires a cross-origin data opt-in, we
must verify that the opt-in check has both been performed and succeeded
before allowing the operation.

This CL updates SharedStorageWorkletHost::IsSharedStorageAllowed to
explicitly check these conditions. If the opt-in is required but
missing or failed, the function now returns false and populates the
debug message with the specific error from the opt-in state.

Bug: 496380960
Change-Id: I748a4ed6ae10dcc7a62466bb8bc0a1098cace0af
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7729481
Reviewed-by: Yao Xiao <[email protected]>
Commit-Queue: Cammie Smith Barnes <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1609953}
---

diff --git a/content/browser/shared_storage/shared_storage_worklet_host.cc b/content/browser/shared_storage/shared_storage_worklet_host.cc
index fc323fb..4f49dbbc 100644
--- a/content/browser/shared_storage/shared_storage_worklet_host.cc
+++ b/content/browser/shared_storage/shared_storage_worklet_host.cc
@@ -1804,6 +1804,17 @@
 bool SharedStorageWorkletHost::IsSharedStorageAllowed(
     std::string* out_debug_message,
     bool* out_block_is_site_setting_specific) {
+  if (needs_data_origin_opt_in_ &&
+      (!data_origin_opt_in_state_ || !data_origin_opt_in_state_->first)) {
+    if (out_debug_message) {
+      *out_debug_message =
+          data_origin_opt_in_state_
+              ? data_origin_opt_in_state_->second
+              : "SharedStorage cross-origin data opt-in check failed.";
+    }
+    return false;
+  }
+
   RenderFrameHost* rfh =
       document_service_ ? &(document_service_->render_frame_host()) : nullptr;
   return GetContentClient()->browser()->IsSharedStorageAllowed(
Loading diff…

Original Bug Report

reported by [email protected]

Race condition in SharedStorageWorkletHost bypasses cross-origin opt-in check

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: A race condition in SharedStorageWorkletHost potentially allows a compromised renderer to access victim Shared Storage data before the mandatory .well-known cross-origin opt-in check completes. This bypasses the security requirement that cross-origin data origins must explicitly opt-in to worklet access via a trusted-origins file. The attacker can indefinitely prolong this access by deliberately hanging the worklet’s script load.

Affected files:

  • content/browser/shared_storage/shared_storage_worklet_host.cc

Estimated timestamp from git blame: 2025-11-25

Vulnerability Description

A race condition exists in SharedStorageWorkletHost that potentially allows a compromised renderer to bypass the cross-origin opt-in requirement for Shared Storage. When a cross-origin worklet is created, the host immediately binds and dispatches the SharedStorageWorkletServiceClient remote to the renderer process before the asynchronous fetch of the mandatory /.well-known/shared-storage/trusted-origins opt-in file has completed.

Because the Mojo receiver for SharedStorageWorkletServiceClient lacks message gating and its storage-accessing handlers (such as SharedStorageGet and SharedStorageUpdate) do not verify the current opt-in state, an attacker-controlled renderer can issue Mojo calls to read or modify a victim’s cross-origin data during the fetch window.

Furthermore, an attacker can extend this window indefinitely by intentionally hanging the fetch of the worklet script (AddModule), preventing the browser from ever evaluating the failed opt-in check and shutting down the worklet.

Potential Attack Steps

(Note: These are suggested steps based on static analysis; a working proof-of-concept has not yet been executed.)

  1. Setup: An attacker compromises a renderer process (e.g., hosting https://attacker.com).
  2. Initiate Worklet Creation: The attacker crafts a CreateWorklet Mojo message over the blink.mojom.SharedStorageDocumentService interface, specifying script_source_url as https://attacker.com/script.js and data_origin as https://victim.com.
  3. Host Initialization: The browser processes this request in SharedStorageDocumentServiceImpl::CreateWorklet. It creates a SharedStorageWorkletHost, which identifies that a cross-origin opt-in is required (needs_data_origin_opt_in_ = true).
  4. Process Allocation: On platforms where strict Site Isolation is not enforced for the target origin (e.g., Android), the SharedStorageRenderThreadWorkletDriver assigns the victim.com worklet to run in the attacker’s compromised renderer process.
  5. Premature Binding: SharedStorageWorkletHost::GetAndConnectToSharedStorageWorkletService() immediately calls Initialize() on the worklet service. This binds the SharedStorageWorkletServiceClient receiver in the browser and dispatches the remote to the compromised renderer before the .well-known opt-in check completes.
  6. Hang Script Load: The attacker configures their server at https://attacker.com/script.js to hang the network fetch indefinitely. This keeps the AddModule script loading state pending.
  7. Exploit Remote: The attacker intercepts the prematurely dispatched SharedStorageWorkletServiceClient remote in their compromised renderer.
  8. Bypass Checks: The attacker immediately sends unauthorized storage-access Mojo messages (e.g., SharedStorageGet). The corresponding handlers in SharedStorageWorkletHost only check general user settings via IsSharedStorageAllowed(), failing to verify the pending .well-known data_origin_opt_in_state_.
  9. Indefinite Access: Even after the asynchronous .well-known check to victim.com eventually fails, MaybeFinishCreateWorklet() returns early because the script load (script_loading_state_) is still pending. The worklet is never expired, granting the attacker an indefinite, unauthorized read/write channel to victim.com’s Shared Storage data.

Impact

This vulnerability constitutes a high-severity cross-origin data leak and modification risk (S1 Site Isolation Bypass). A compromised renderer can perform unauthorized operations against a victim’s Shared Storage, completely bypassing the .well-known opt-in security mechanism.

Ensure that the SharedStorageWorkletServiceClient Mojo receiver does not process messages until the .well-known opt-in check has successfully completed. This can be achieved by:

  1. Deferring Binding: Wait to bind and dispatch the SharedStorageWorkletServiceClient remote until data_origin_opt_in_state_ is successfully resolved in MaybeFinishCreateWorklet().
  2. Explicit Checks: Alternatively, add an explicit check for a successful data_origin_opt_in_state_ in all storage-accessing Mojo handlers within SharedStorageWorkletHost (e.g., SharedStorageGet, SharedStorageUpdate, etc.) when needs_data_origin_opt_in_ is true.

Evaluated with Chrome root at commit: 0eb4855bda702feaaa8b899336664f97e3df88b8


Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. Please feel free to reach out to me if you have concerns or feedback.

View on issue tracker