Critical watch CVSS 8.8 chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Critical
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactObject lifecycle issue in WebShare
DescriptionObject lifecycle issue in WebShare
ComponentWebShare
Sub-componentWebShare
Bug ClassLogic Error
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable
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.
Tracker497531263
Fix commit33390cb84fac (chromium/src) +2/-2
CWECWE-664
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-03-29 (per vendor advisory)
Fix landed2026-03-30 (public git)
Disclosed2026-05-12
Patch gap43 days — fix public in source before the advisory

Background

WebShare on Windows (`share_operation.cc`)
the browser-side implementation that fulfills navigator.share() by streaming shared data (e.g. a blob) into a Windows IOutputStream for the OS share UI.
`OutputStreamWriteOperation`
a reference-counted helper object representing one in-progress write of blob data to the IOutputStream, kept alive by outstanding scoped_refptr references across asynchronous steps.
`base::RefCounted` vs `base::RefCountedThreadSafe`
the former increments/decrements the reference count with plain non-atomic operations valid only on a single sequence, while the latter uses atomic operations safe across threads.
Blob reading
reading blob contents is asynchronous and can hop between the UI/IO sequences and the blob storage context, so references to the operation may be added or dropped from more than one thread.

Root Cause Analysis

OutputStreamWriteOperation was declared as base::RefCounted<OutputStreamWriteOperation>, so every AddRef/Release used non-atomic reference-count arithmetic that is only correct when all such operations happen on a single sequence. Because the write operation drives asynchronous blob reads and IOutputStream writes whose callbacks can run on different threads, scoped_refptr copies were being created and destroyed concurrently, producing a data race on the reference counter. A lost decrement or interleaved update can drop the count to zero prematurely (freeing the object while another reference still points at it) or corrupt it, an object-lifecycle error.

The fix changes the base class to base::RefCountedThreadSafe<OutputStreamWriteOperation> (and the matching friend declaration), making all reference-count updates atomic so the object’s lifetime is managed correctly regardless of which thread adds or releases a reference.

Key insight
A ref-counted object whose references were manipulated from multiple threads used the non-thread-safe base::RefCounted, allowing a racy refcount to free it prematurely; the fix switches it to base::RefCountedThreadSafe so all AddRef/Release operations are atomic.

Attack Path

  1. Invoke Web Share Web content calls navigator.share() with data (such as a blob) on Windows, creating an OutputStreamWriteOperation to stream the payload into the OS share target.
  2. Concurrent reference churn The operation’s asynchronous blob reads and stream writes run their callbacks on different threads, each copying and dropping scoped_refptr<OutputStreamWriteOperation> references.
  3. Refcount race Non-atomic AddRef/Release interleave, so the reference count is updated incorrectly and reaches zero while a live reference still exists, destroying the object early.
  4. Use-after-free A surviving reference or in-flight callback then accesses the freed OutputStreamWriteOperation (the use-after-free and any further primitive are inferred; the diff demonstrates only the switch to a thread-safe refcount).

Impact Assessment

The flaw is an object-lifecycle bug in the browser process on Windows, where a non-atomic reference count on an asynchronous WebShare write operation can be corrupted by concurrent access, leading to premature destruction and a probable use-after-free (inferred); the vendor advisory rates it critical and labels it an object lifecycle issue in WebShare. Preconditions include the Windows platform and a page invoking the Web Share API (normally gated behind a user gesture / share picker), with the race depending on timing between the blob-read and stream-write threads.

Changed Functions

FunctionChangeNotes
OutputStreamWriteOperation
chrome/browser/webshare/win/share_operation.cc
modified

Files Changed

  • chrome/browser/webshare/win/share_operation.cc

Audit Directions

  • `base::RefCounted` on async/multi-thread objects
    Audit ref-counted types whose scoped_refptrs are passed into callbacks posted to other sequences or threads; these must use base::RefCountedThreadSafe.
  • Cross-thread blob/stream pipelines
    Review other platform share/upload/stream helpers that drive IOutputStream or blob reads, where completion callbacks hop threads, for the same non-atomic-refcount pattern.
  • Mismatch between threading model and refcount class
    Look for objects documented or implemented as single-sequence but whose work (I/O, OS callbacks, thread pool) actually spans threads, a reliable signal of a refcount thread-safety mismatch.
From 33390cb84faca1aa2deff0cc3b49d6f260e17994 Mon Sep 17 00:00:00 2001
From: Andrew Paseltiner <apaseltiner@chromium.org>
Date: Mon, 30 Mar 2026 09:17:53 -0700
Subject: [PATCH] [WebShare] Use RefCountedThreadSafe for OutputStreamWriteOperation

Fixed: 497531263
Change-Id: I668a976f66d8ffa3d8a0f4d8c06ca0dfa05f185f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7711320
Commit-Queue: Andrew Paseltiner <apaseltiner@chromium.org>
Reviewed-by: Daniel Murphy <dmurph@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1607144}
---

diff --git a/chrome/browser/webshare/win/share_operation.cc b/chrome/browser/webshare/win/share_operation.cc
index 95fa446e..1eeb3cf 100644
--- a/chrome/browser/webshare/win/share_operation.cc
+++ b/chrome/browser/webshare/win/share_operation.cc
@@ -230,7 +230,7 @@
 
 // Represents an ongoing operation of writing to an IOutputStream.
 class OutputStreamWriteOperation
-    : public base::RefCounted<OutputStreamWriteOperation> {
+    : public base::RefCountedThreadSafe<OutputStreamWriteOperation> {
  public:
   OutputStreamWriteOperation(
       content::BrowserContext::BlobContextGetter blob_context_getter,
@@ -257,7 +257,7 @@
   }
 
  private:
-  friend class base::RefCounted<OutputStreamWriteOperation>;
+  friend class base::RefCountedThreadSafe<OutputStreamWriteOperation>;
 
   ~OutputStreamWriteOperation() = default;
 
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential Browser Process Double-Free via Race Condition in OutputStreamWriteOperation

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

Overview: A race condition exists in the Windows Web Share API where OutputStreamWriteOperation incorrectly inherits from base::RefCounted instead of base::RefCountedThreadSafe. Concurrent releases across the Chrome IO thread and WinRT background threads can trigger a double-free in the browser process. This could potentially be leveraged for sandbox escape and Remote Code Execution.

Affected files:

  • chrome/browser/webshare/win/share_operation.cc

Estimated timestamp from git blame: 2020-10-28

Vulnerability Details

Initial logic and parameters for the Web Share API are validated. The IPC routing from the renderer to the browser process and the instantiation of OutputStreamWriteOperation proceed per standard Windows share mechanisms. The core architectural flaw lies in the class inheritance: OutputStreamWriteOperation (in chrome/browser/webshare/win/share_operation.cc) derives from the non-thread-safe base::RefCounted rather than base::RefCountedThreadSafe.

Standard processing applies during the cross-thread handoff between the Chrome IO thread (handling file blob writing) and the OS-managed WinRT background threads (handling the IStreamedFileDataRequestedHandler COM object).

Because base::RefCounted relies on a non-atomic uint32_t for its reference count, concurrent destruction of the scoped_refptr instances on the IO thread and the WinRT thread bypasses thread-safety. Both threads simultaneously execute the out-of-line ReleaseImpl(), non-atomically decrement the counter, and subsequently reload ref_count_ from memory. Both threads observe ref_count_ == 0 and independently execute the destructor, resulting in a double-free in the highly privileged browser process.

Because the frees occur on separate threads, PartitionAlloc routes the pointers into separate ThreadCaches, bypassing FreeList corruption detection and cleanly exposing the memory to overlapping allocations.

Potential Attacker Steps

(Note: These are suggested/potential steps, our tooling agent doesn’t yet have the ability to run code.)

  1. Host a malicious page that constructs a file array and invokes navigator.share().
  2. Standard UI interaction processing applied (user selects a share target).
  3. Exploit overlapping PartitionAlloc ThreadCaches resulting from the concurrent double-free to achieve type confusion on the reallocated object.
  4. Hijack control flow (e.g., via writer_delegate_ virtual calls) to achieve arbitrary code execution and a full sandbox escape.

Suggested Fix

In chrome/browser/webshare/win/share_operation.cc, update the class definition to use atomic reference counting:

class OutputStreamWriteOperation
    : public base::RefCountedThreadSafe<OutputStreamWriteOperation> {
...
  friend class base::RefCountedThreadSafe<OutputStreamWriteOperation>;
...

Evaluated with Chrome root at commit: a9cbf6e8b275fe4147435aa905f3b7f5a656f5f0


Results from 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. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker