CVE-2026-10890
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifcomponents/openscreen_platform/udp_socket.cc |
modified |
Files Changed
components/openscreen_platform/udp_socket.cc
Patch
From 034c57cb7a2a215024822b53ab27b860e05fd348 Mon Sep 17 00:00:00 2001
From: Jordan Bayles <jophba@chromium.org>
Date: Mon, 18 May 2026 16:34:50 -0700
Subject: [PATCH] Fix UAF in openscreen_platform::UdpSocket::OnReceived
This CL adds a weak pointer guard before calling udp_socket_->ReceiveMore(1) in UdpSocket::OnReceived to prevent a Use-After-Free if the client's OnRead callback synchronously destroys the UdpSocket instance.
Bug: 513136593
Change-Id: I6253d17915b1c03488d403117dbf6edca30dc4bd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7856453
Reviewed-by: Muyao Xu <muyaoxu@google.com>
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Commit-Queue: Muyao Xu <muyaoxu@google.com>
Auto-Submit: Jordan Bayles <jophba@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1632485}
---
diff --git a/components/openscreen_platform/udp_socket.cc b/components/openscreen_platform/udp_socket.cc
index 1fc4bf3..ff858f8a 100644
--- a/components/openscreen_platform/udp_socket.cc
+++ b/components/openscreen_platform/udp_socket.cc
@@ -152,6 +152,7 @@
int32_t net_result,
const std::optional<net::IPEndPoint>& source_endpoint,
std::optional<base::span<const uint8_t>> data) {
+ base::WeakPtr<UdpSocket> weak_this = weak_ptr_factory_.GetWeakPtr();
if (net_result != net::OK) {
client_->OnRead(this, Error::Code::kSocketReadFailure);
} else if (data) {
@@ -163,7 +164,9 @@
client_->OnRead(this, std::move(packet));
}
- udp_socket_->ReceiveMore(1);
+ if (weak_this) {
+ udp_socket_->ReceiveMore(1);
+ }
}
void UdpSocket::BindCallback(int32_t result,
Original Bug Report
Potential Browser-process UAF in openscreen_platform::UdpSocket::OnReceived
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 Use-After-Free (UAF) vulnerability potentially exists in the browser process within openscreen_platform::UdpSocket::OnReceived. A reentrant callback can synchronously trigger the destruction of the UdpSocket instance, leading to an invalid member access when execution returns to the function.
Affected files:
components/openscreen_platform/udp_socket.cccomponents/openscreen_platform/udp_socket.h
Estimated timestamp from git blame: 2019-10-21
Root Cause Analysis
A potential Use-After-Free (UAF) has been identified in openscreen_platform::UdpSocket::OnReceived in components/openscreen_platform/udp_socket.cc. This method is the handler for network::mojom::UDPSocketListener, which is dispatched by a mojo::Receiver stored within the UdpSocket object.
When a network error or a specific packet is received, OnReceived calls a client callback (client_->OnRead). In certain configurations, such as the Cast receiver’s streaming application, this callback can trigger a synchronous teardown of the ownership chain that includes the UdpSocket instance. Because this destruction is synchronous, the UdpSocket object (including its this pointer and all members) is freed before the callback returns. Execution then proceeds to access the udp_socket_ member of the now-deleted object.
In components/openscreen_platform/udp_socket.cc:
void UdpSocket::OnReceived(
int32_t net_result,
const std::optional<net::IPEndPoint>& source_endpoint,
std::optional<base::span<const uint8_t>> data) {
if (net_result != net::OK) {
client_->OnRead(this, Error::Code::kSocketReadFailure); // (A) Synchronous callback
} else if (data) {
// ... packet processing ...
client_->OnRead(this, std::move(packet)); // (A') Synchronous callback
}
udp_socket_->ReceiveMore(1); // (B) UAF access here
}
The udp_socket_ member is a mojo::Remote<network::mojom::UDPSocket>. Since the access occurs on a freed this pointer and the member is a value type, MiraclePtr (BRP) does not provide protection in this specific code path.
Potential Destruction Chain
Based on code analysis, a suggested sequence for triggering the synchronous destruction in a Cast receiver context is:
UdpSocket::OnReceivedis called with a network error (net_result != net::OK).client_->OnReadis called, which notifies theopenscreen::cast::Environment(third_party/openscreen/src/cast/streaming/public/environment.cc:145).- The error propagates synchronously:
Environment::OnError->ReceiverSession::OnSocketInvalid->ReceiverSessionClient::OnError(components/cast_streaming/browser/cast_streaming_session.cc:487). - The application layer handles the error by calling
StopApplication(), which executesreceiver_session_client_.reset()(components/cast_receiver/browser/streaming_runtime_application.cc:100). - This triggers a synchronous cascade of destructors, eventually calling
~UdpSocket()and freeing the memory whileOnReceivedis still on the stack. - Control returns to
UdpSocket::OnReceived, which dereferences the destructedudp_socket_member.
Impact
This is a browser-process UAF. An attacker who can trigger this state (e.g., a compromised network process or potentially via crafted local network traffic in a Cast receiver environment) could achieve arbitrary code execution in the browser process by performing heap grooming during the synchronous teardown to control the freed memory.
Suggested Fix
The call to udp_socket_->ReceiveMore(1) should be guarded by a weak pointer check to ensure the object still exists after the client callback returns.
void UdpSocket::OnReceived(...) {
base::WeakPtr<UdpSocket> weak_this = weak_ptr_factory_.GetWeakPtr();
// ... existing callback logic ...
if (weak_this) {
udp_socket_->ReceiveMore(1);
}
}
Alternatively, ensure that the destruction of the streaming session always occurs asynchronously (e.g., via base::SequencedTaskRunner::PostTask).
Evaluated with Chrome root at commit: b3153093eb3c78c3e88ccf562bcbc20437a04b0e
Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:
- If you are familiar with the severity guidelines, you may adjust the severity.
- If this is a false positive, and there’s no work to be done, please close as WAI.
- If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.
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.