Overview

Critical
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Cast Streaming
DescriptionUse after free in Cast Streaming
ComponentCast Streaming
Bug ClassUAF
Tracker505815080
Fix commitccc2bc32526c (chromium/src) +5/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Changed Functions

FunctionChangeNotes
if
components/cast_streaming/browser/cast_streaming_session.cc
modified

Files Changed

  • components/cast_streaming/browser/cast_streaming_session.cc
  • components/cast_streaming/browser/control/playback_command_dispatcher.cc
From ccc2bc32526cd2292ffb623409e70da00ea4ae16 Mon Sep 17 00:00:00 2001
From: Jordan Bayles <jophba@chromium.org>
Date: Mon, 27 Apr 2026 16:12:46 -0700
Subject: [PATCH] [cast_streaming] Fix potential UAF and re-entrancy in CastStreamingSession

This CL addresses two potential issues in CastStreamingSession:
1. A Use-After-Free (UAF) risk where deferred StartStreamingSession
   callbacks could hold dangling pointers to receivers if
   OnReceiversDestroying is called while a flush is pending.
2. A re-entrancy UAF during destruction if OnCastChannelClosed is
   triggered while ReceiverSession is being reset.

Specifically:
- Clear start_session_cb_ in OnReceiversDestroying and EndSession.
- Call weak_factory_.InvalidateWeakPtrs() in ~ReceiverSessionClient.
- Update PlaybackCommandDispatcher to clear streaming_dispatcher_ on
  session end.

Bug: 505815080
Change-Id: I9221f0b2a033778077d920805e6eed73759c4264
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7797771
Reviewed-by: Simeon Anfinrud <sanfin@chromium.org>
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1621401}
---

diff --git a/components/cast_streaming/browser/cast_streaming_session.cc b/components/cast_streaming/browser/cast_streaming_session.cc
index c041964c..471c14a 100644
--- a/components/cast_streaming/browser/cast_streaming_session.cc
+++ b/components/cast_streaming/browser/cast_streaming_session.cc
@@ -201,6 +201,7 @@
 }
 
 CastStreamingSession::ReceiverSessionClient::~ReceiverSessionClient() {
+  weak_factory_.InvalidateWeakPtrs();
   client_ = nullptr;
   // Teardown of the `receiver_session_` may trigger callbacks into `this`,
   // so destroy it explicitly here, so that callbacks execute while all other
@@ -428,6 +429,8 @@
     playback_command_dispatcher_->OnRemotingSessionEnded();
   }
 
+  start_session_cb_.Reset();
+
   preloaded_audio_buffer_ = std::nullopt;
   preloaded_video_buffer_ = std::nullopt;
 
@@ -517,6 +520,7 @@
 }
 
 void CastStreamingSession::ReceiverSessionClient::EndSession() {
+  start_session_cb_.Reset();
   if (client_) {
     CastStreamingSession::Client* client = client_;
     client_ = nullptr;
diff --git a/components/cast_streaming/browser/control/playback_command_dispatcher.cc b/components/cast_streaming/browser/control/playback_command_dispatcher.cc
index 0d98647e..cac251f7 100644
--- a/components/cast_streaming/browser/control/playback_command_dispatcher.cc
+++ b/components/cast_streaming/browser/control/playback_command_dispatcher.cc
@@ -173,6 +173,7 @@
   demuxer_stream_handler_.reset();
   messenger_ = nullptr;
   streaming_init_info_ = std::nullopt;
+  streaming_dispatcher_ = nullptr;
 }
 
 void PlaybackCommandDispatcher::SendRemotingRpcMessageToRemote(
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential Use-After-Free in CastStreamingSession via deferred callback binding dangling Receivers

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the Chrome Security team. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A race condition during session renegotiation in CastStreamingSession can lead to a Use-After-Free in the browser process. A pending async flush defers session initialization, capturing openscreen::cast::Receiver pointers in a callback that is not cleared when those receivers are subsequently destroyed by a rapid third renegotiation. This leads to a virtual call on freed memory.

Affected files:

  • components/cast_streaming/browser/cast_streaming_session.cc
  • components/cast_streaming/browser/cast_streaming_session.h
  • components/cast_streaming/browser/frame/stream_consumer.cc
  • components/cast_streaming/browser/common/streaming_initialization_info.h

Estimated timestamp from git blame: 2023-02-02

Overview

A potential Use-After-Free (UAF) vulnerability exists in the CastStreamingSession component within the browser process. The issue stems from the deferred execution of session start logic when a renderer-side flush is pending, combined with a failure to invalidate this deferred state when session receivers are destroyed during a rapid renegotiation.

Root Cause

When a Cast Streaming remoting session is negotiated, openscreen::cast::ReceiverSession creates Receiver objects for audio and video streams.

If a session renegotiation occurs (e.g., a new OFFER message arrives), openscreen tears down the old receivers. It calls CastStreamingSession::ReceiverSessionClient::OnReceiversDestroying, which initiates an asynchronous Mojo Flush() to the renderer and sets is_flush_pending_ = true.

If initialization configuration for the new session arrives before the Flush() completes, StartStreamingSession is called. Because is_flush_pending_ is true, it defers execution by storing a StreamingInitializationInfo struct inside a callback (start_session_cb_). Crucially, this struct holds raw_ptrs to the current Receiver objects.

If the attacker initiates a third session renegotiation before the original Flush() completes, openscreen again tears down the current receivers. OnReceiversDestroying is called again, but it fails to clear or invalidate start_session_cb_. openscreen then deletes the Receiver objects.

When the asynchronous Flush() finally completes, OnFlushComplete() executes the stale start_session_cb_. This resumes StartStreamingSession, passing the dangling Receiver pointers to the StreamConsumer constructor, which immediately performs a virtual call (receiver_->SetConsumer(this)) on the freed object.

Potential Exploitation Steps

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

An attacker on the local network can trigger this by pipelining Cast-channel messages:

  1. Transmit an initial remoting OFFER (#1) to establish Session 1.
  2. Transmit a second remoting OFFER (#2). This destroys Session 1, triggering the async Flush(), and creates Session 2 receivers.
  3. Immediately transmit RPC initialization calls for Session 2. This populates the configs and triggers StartStreamingSession, which defers execution into start_session_cb_ (capturing Session 2’s receiver pointers) because the flush is pending.
  4. Immediately transmit a third remoting OFFER (#3). This destroys Session 2’s receivers. start_session_cb_ is not cleared.
  5. Wait for the asynchronous Flush() to complete. OnFlushComplete runs start_session_cb_, resulting in the UAF and vtable hijack in StreamConsumer::StreamConsumer.

Impact

This vulnerability occurs in the highly privileged Browser process. While the affected pointers are wrapped in raw_ptr, BackupRefPtr (BRP) is currently disabled by default on CastOS (!is_castos). Therefore, the raw_ptr wrapper provides no protection via partitioning or quarantining, making the UAF potentially exploitable for arbitrary Remote Code Execution.

Suggested Fix

In CastStreamingSession::ReceiverSessionClient::OnReceiversDestroying, explicitly clear the deferred callback when the receivers are being destroyed. For example:

if (start_session_cb_) {
  start_session_cb_.Reset();
}

Evaluated with Chrome root at commit: 3acbde3302da0cb19488c22c0eb007c791207b4b


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

View on issue tracker