CVE-2026-10975
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
rtc_source_setrtc_base/BUILD.gn |
modified | |
rtc_libraryrtc_base/BUILD.gn |
modified | |
RefCounterrtc_base/ref_counter.h |
modified | |
RTC_EXPORTrtc_base/ref_counter.h |
modified |
Files Changed
api/peer_connection_interface.hpc/peer_connection_factory.ccrtc_base/BUILD.gnrtc_base/ref_counter.ccrtc_base/ref_counter.h
Patch
From 34505048c030ee72ad6ee99f46534861ebb0e365 Mon Sep 17 00:00:00 2001
From: Tommi <tommi@webrtc.org>
Date: Mon, 18 May 2026 08:36:02 +0200
Subject: [PATCH] Cap RTCConfiguration certificates and enforce 32-bit overflow checks
1. Bounded the maximum number of certificates in RTCConfiguration to
1000 to prevent reference counter overflow while maintaining ample
headroom for legitimate multi-algorithm DTLS interoperability.
2. Updated webrtc_impl::RefCounter to declare IncRef() out-of-line
unconditionally across all architectures.
3. Implemented RefCounter::IncRef() out-of-line in ref_counter.cc with
an explicit RTC_CHECK_LT(prev, INT_MAX) guard on all architectures,
preventing 32-bit integer overflow and Use-After-Free vulnerabilities
unconditionally without causing inlined binary bloat.
Bug: chromium:513154132
Fixed: chromium:513154132
Change-Id: I9894ef08519423b24139b0250cc9da0f9737827a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/472722
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#47722}
---
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
index 6c51d77..da0f292 100644
--- a/api/peer_connection_interface.h
+++ b/api/peer_connection_interface.h
@@ -417,6 +417,10 @@
static const int kAudioJitterBufferMaxPackets = 200;
// ICE connection receiving timeout for aggressive configuration.
static const int kAggressiveIceConnectionReceivingTimeout = 1000;
+ // Maximum number of certificates allowed in the configuration.
+ // Capped at 1000 which still provides ample headroom for interoperability
+ // of multiple key algorithms.
+ static const int kMaxCertificates = 1000;
////////////////////////////////////////////////////////////////////////
// The below few fields mirror the standard RTCConfiguration dictionary:
diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc
index d36b766..9e9e402 100644
--- a/pc/peer_connection_factory.cc
+++ b/pc/peer_connection_factory.cc
@@ -240,6 +240,12 @@
return err;
}
+ if (configuration.certificates.size() >
+ PeerConnectionInterface::RTCConfiguration::kMaxCertificates) {
+ return RTCError(RTCErrorType::INVALID_PARAMETER,
+ "Too many certificates in RTCConfiguration.");
+ }
+
ServerAddresses stun_servers;
std::vector<RelayServerConfig> turn_servers;
err = ParseAndValidateIceServersFromConfiguration(configuration, stun_servers,
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index f156680..5a306a6 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -459,14 +459,19 @@
deps = [ ":checks" ]
}
-rtc_source_set("refcount") {
+rtc_library("refcount") {
visibility = [ "*" ]
sources = [
"ref_count.h",
"ref_counted_object.h",
+ "ref_counter.cc",
"ref_counter.h",
]
- deps = [ "../api:ref_count" ]
+ deps = [
+ ":checks",
+ "../api:ref_count",
+ "system:rtc_export",
+ ]
}
rtc_library("criticalsection") {
diff --git a/rtc_base/ref_counter.cc b/rtc_base/ref_counter.cc
new file mode 100644
index 0000000..bc3c6a7
--- /dev/null
+++ b/rtc_base/ref_counter.cc
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2026 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/ref_counter.h"
+
+#include <atomic>
+#include <climits>
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace webrtc_impl {
+
+void RefCounter::IncRef() {
+ // Relaxed memory order: The current thread is allowed to act on the
+ // resource protected by the reference counter both before and after the
+ // atomic op, so this function doesn't prevent memory access reordering.
+ int prev = ref_count_.fetch_add(1, std::memory_order_relaxed);
+ RTC_CHECK_LT(prev, INT_MAX);
+}
+
+} // namespace webrtc_impl
+} // namespace webrtc
diff --git a/rtc_base/ref_counter.h b/rtc_base/ref_counter.h
index af25391..6e52e4e 100644
--- a/rtc_base/ref_counter.h
+++ b/rtc_base/ref_counter.h
@@ -13,21 +13,17 @@
#include <atomic>
#include "api/ref_count.h"
+#include "rtc_base/system/rtc_export.h"
namespace webrtc {
namespace webrtc_impl {
-class RefCounter {
+class RTC_EXPORT RefCounter {
public:
explicit RefCounter(int ref_count) : ref_count_(ref_count) {}
RefCounter() = delete;
- void IncRef() {
- // Relaxed memory order: The current thread is allowed to act on the
- // resource protected by the reference counter both before and after the
- // atomic op, so this function doesn't prevent memory access reordering.
- ref_count_.fetch_add(1, std::memory_order_relaxed);
- }
+ void IncRef();
// Returns kDroppedLastRef if this call dropped the last reference; the caller
// should therefore free the resource protected by the reference counter.
Original Bug Report
32-bit RefCounter overflow in WebRTC leads to Use-After-Free of RTCCertificate
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: WebRTC’s RefCounter uses a 32-bit signed atomic integer without overflow checks, allowing the reference count to wrap around. An attacker could potentially exploit this by supplying a large number of duplicate certificates in the RTCConfiguration to trigger a Use-After-Free of an RTCCertificate. These references are not protected by MiraclePtr, making the issue potentially exploitable in the renderer process.
Affected files:
third_party/webrtc/rtc_base/ref_counter.hthird_party/webrtc/api/ref_counted_base.hthird_party/blink/renderer/modules/peerconnection/rtc_configuration.idlthird_party/blink/renderer/modules/peerconnection/rtc_peer_connection.ccthird_party/webrtc/rtc_base/rtc_certificate.h
Estimated timestamp from git blame: 2017-11-01
Summary
A potential Use-After-Free (UAF) vulnerability exists in WebRTC due to a 32-bit reference counter overflow in the webrtc_impl::RefCounter class. This class is used to manage the lifecycle of webrtc::RTCCertificate objects. By supplying a large number of duplicate certificates in an RTCConfiguration, an attacker might be able to cause the reference count to wrap around, leading to the premature deletion of the certificate object while references still exist.
Root Cause Analysis
The issue is located in third_party/webrtc/rtc_base/ref_counter.h. The RefCounter class uses a std::atomic<int> (which is a 32-bit signed integer on all Chromium-supported platforms) to store the reference count. The IncRef() method increments this count using fetch_add without saturation or overflow checks:
// third_party/webrtc/rtc_base/ref_counter.h
void IncRef() {
ref_count_.fetch_add(1, std::memory_order_relaxed);
}
Atomic fetch_add on signed integers is defined to wrap around modulo 2^N. When the counter wraps and eventually returns to a low value (e.g., 1), a subsequent Release() call will see the counter reach zero, triggering the object’s destruction via delete this in third_party/webrtc/api/ref_counted_base.h.
This implementation differs from Chromium’s base::RefCounted, which includes explicit CHECKs to prevent overflow on 64-bit systems.
Potential Trigger Path
An attacker might be able to drive the reference count to overflow through the following suggested steps:
- Unbounded Sequence: The
RTCConfiguration.certificatessequence is defined in Blink’s IDL without a length limit. An attacker can generate a single certificate and create a JavaScript array containing millions of references to it (e.g., 4.3 million). - Configuration Conversion: When creating an
RTCPeerConnection, Blink converts this sequence into astd::vector<scoped_refptr<RTCCertificate>>. Each entry increments the certificate’s reference count. [third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc:387] - Multiple Copies: Persistent copies of the configuration are maintained in
RTCPeerConnectionHandlerandwebrtc::PeerConnection. With a limit of 500 activeRTCPeerConnections per renderer, an attacker can theoretically create enough references (~2^32) to cause an overflow, requiring approximately 34GB of memory on a 64-bit system. - Use-After-Free: Once the counter wraps, destroying one
RTCPeerConnection(or triggering garbage collection) causes the counter to reach zero, deleting theRTCCertificate. Billions of danglingscoped_refptrs remain in the other active connections.
Impact
webrtc::scoped_refptr is a separate implementation from Chromium’s smart pointers and does not use base::raw_ptr, meaning it lacks MiraclePtr (BackupRefPtr) protection. A UAF here could allow an attacker to reclaim the freed memory and then call methods like getFingerprints() on a dangling reference. This triggers a virtual call on the underlying SSLIdentity object, potentially allowing for arbitrary code execution (RCE) within the sandboxed renderer.
Suggested Fix
The webrtc_impl::RefCounter should be updated to include overflow checks, similar to base::RefCounted. Specifically, IncRef() should CHECK that the increment does not result in a wrap-around to zero or a negative value.
void IncRef() {
int prev = ref_count_.fetch_add(1, std::memory_order_relaxed);
CHECK_GT(prev, 0);
}
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.