Low chrome Integer Overflow 📄 Reporter bug report 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInteger overflow in WebRTC
DescriptionInteger overflow in WebRTC
ComponentWebRTC
Bug ClassInteger Overflow
Tracker501881082
Fix commit5207e12e4866 (chromium/src) +36/-0
CISA KEVNot listed
CreditedAshutosh
Disclosed2026-08-25

Changed Functions

FunctionChangeNotes
for
third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
modified

Files Changed

  • third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
  • third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
  • third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
  • third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html
From 5207e12e48669e9f2a924cc77d51bcaf57efbedf Mon Sep 17 00:00:00 2001
From: Tommi <[email protected]>
Date: Mon, 27 Jul 2026 05:33:07 -0700
Subject: [PATCH] Fix rtp sender max bitrate

Reject maxBitrate = 0 in setParameters and addTransceiver.

Bug: 501881082, 501879826
Change-Id: Ia2f70e2c561deff3ad00595a31089078f8417250
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8148539
Reviewed-by: Guido Urdaneta <[email protected]>
Commit-Queue: Tomas Gunnarsson <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1668537}
---

diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index c31760f..2256945 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -2031,6 +2031,15 @@
     ExceptionState& exception_state,
     const RTCRtpTransceiverInit* init,
     const String kind) {
+  if (init->hasSendEncodings()) {
+    for (const auto& encoding : init->sendEncodings()) {
+      if (encoding->hasMaxBitrate() && encoding->maxBitrate() == 0) {
+        exception_state.ThrowRangeError("maxBitrate must be greater than 0.");
+        return std::nullopt;
+      }
+    }
+  }
+
   auto webrtc_init = ToRtpTransceiverInit(execution_context, init, kind);
   // Validate sendEncodings.
   for (auto& encoding : webrtc_init.send_encodings) {
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
index 8d89499..e76fb187 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -822,6 +822,16 @@
     const RTCSetParameterOptions* options,
     ExceptionState& exception_state) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  if (parameters->hasEncodings()) {
+    for (const auto& encoding : parameters->encodings()) {
+      if (encoding->hasMaxBitrate() && encoding->maxBitrate() == 0) {
+        exception_state.ThrowRangeError("maxBitrate must be greater than 0.");
+        return EmptyPromise();
+      }
+    }
+  }
+
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver<IDLUndefined>>(
       script_state, exception_state.GetContext());
   auto promise = resolver->Promise();
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
index 1a81319c..ed04478 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
@@ -88,6 +88,14 @@
     assert_throws_js(TypeError, () => pc.addTransceiver('invalid'));
   }, 'addTransceiver() with string argument as invalid kind should throw TypeError');
 
+  test(t => {
+    const pc = new RTCPeerConnection();
+    t.add_cleanup(() => pc.close());
+    assert_throws_js(RangeError, () => pc.addTransceiver('audio', {
+      sendEncodings: [{ maxBitrate: 0 }]
+    }));
+  }, 'addTransceiver() with maxBitrate set to 0 should throw RangeError');
+
   /*
     5.1.  addTransceiver
       The initial value of mid is null.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html
index 3c03184..4c26c84 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html
@@ -56,4 +56,13 @@
   }, `setParameters() with already used parameters should reject with InvalidStateError if the event loop has been relinquished`);
 }
 
+  promise_test(async t => {
+    const pc = new RTCPeerConnection();
+    t.add_cleanup(() => pc.close());
+    const { sender } = pc.addTransceiver('audio');
+    const param = sender.getParameters();
+    param.encodings[0].maxBitrate = 0;
+    await promise_rejects_js(t, RangeError, sender.setParameters(param));
+  }, `setParameters() with maxBitrate set to 0 should reject with RangeError`);
+
 </script>
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
index 1a81319c..ed04478 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
@@ -88,6 +88,14 @@
     assert_throws_js(TypeError, () => pc.addTransceiver('invalid'));
   }, 'addTransceiver() with string argument as invalid kind should throw TypeError');
 
+  test(t => {
+    const pc = new RTCPeerConnection();
+    t.add_cleanup(() => pc.close());
+    assert_throws_js(RangeError, () => pc.addTransceiver('audio', {
+      sendEncodings: [{ maxBitrate: 0 }]
+    }));
+  }, 'addTransceiver() with maxBitrate set to 0 should throw RangeError');
+
   /*
     5.1.  addTransceiver
       The initial value of mid is null.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html
index 3c03184..4c26c84 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters.html
@@ -56,4 +56,13 @@
   }, `setParameters() with already used parameters should reject with InvalidStateError if the event loop has been relinquished`);
 }
 
+  promise_test(async t => {
+    const pc = new RTCPeerConnection();
+    t.add_cleanup(() => pc.close());
+    const { sender } = pc.addTransceiver('audio');
+    const param = sender.getParameters();
+    param.encodings[0].maxBitrate = 0;
+    await promise_rejects_js(t, RangeError, sender.setParameters(param));
+  }, `setParameters() with maxBitrate set to 0 should reject with RangeError`);
+
 </script>
Loading diff…

Original Bug Report

reported by [email protected]

RTCRtpSender.setParameters accepts maxBitrate > UINT32_MAX (MAX_SAFE_INTEGER, -1) without TypeError. WebIDL unsigned long spec violation. uint32→int32 cast is undefined behavior in C++.


Report description

RTCRtpSender.setParameters accepts maxBitrate > UINT32_MAX (MAX_SAFE_INTEGER, -1) without TypeError. WebIDL unsigned long spec violation. uint32→int32 cast is undefined behavior in C++.


Bug location

Where do you want to report your vulnerability?

Chrome VRP – Report security issues affecting the Chrome browser. See program rules

Which URL (or repository) have you found the vulnerability in?

https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/peerconnection/


The problem

Please describe the technical details of the vulnerability

Summary

RTCRtpSender.setParameters() accepts maxBitrate values exceeding the uint32 range without throwing TypeError, violating the WebIDL spec.

The WebRTC spec defines maxBitrate as WebIDL unsigned long, which maps to uint32_t (0 to 4,294,967,295). Per WebIDL §3.2.5, converting values outside this range should produce specific results:

  • Values > 2^32 should be modulo-reduced (ToUint32)
  • NaN should become 0
  • Infinity should become 0 (via ToUint32)

However, the actual behavior shows these values are silently accepted and the truncated/converted values are passed to the internal BitrateAllocator where max_bitrate_bps is stored as std::optional<int> (signed 32-bit).

Tested Values

Input WebIDL ToUint32 Stored as int32 Expected Actual
4294967295 (UINT32_MAX) 4294967295 OVERFLOW (UB) Accept Accept
4294967296 (UINT32_MAX+1) 0 0 Accept(0) Accept
MAX_SAFE_INTEGER 4294967295 OVERFLOW (UB) Accept(ff) Accept
Infinity 0 0 Accept(0) Accept
-1 4294967295 OVERFLOW (UB) Accept(ff) Accept

The critical issue is that std::optional<int> cannot hold 4,294,967,295. Storing UINT32_MAX in a signed int32 is undefined behavior in C++.

Root Cause

In third_party/webrtc/api/rtp_parameters.h:

  • max_bitrate_bps is std::optional<int> (signed 32-bit)
  • WebIDL produces uint32 values up to 4,294,967,295
  • Assigning uint32 > INT32_MAX to int is undefined behavior
  • UBSan would flag: “value 4294967295 is outside the range of representable values of type ‘int’”

Security Impact

  1. UndefinedBehavior in C++ can be exploited by compilers to optimize away safety checks
  2. The BitrateAllocator receives a corrupted max_bitrate value, potentially causing integer overflow in bandwidth calculations
  3. Multiple senders with UINT32_MAX maxBitrate: sum overflows both int32 and uint32 (3 × 4294967295 = 12,884,901,885)

Reproduction

  1. Open attached v7_webidl_violation_poc.html
  2. Wait for Phase 1 to complete
  3. Observe that values > UINT32_MAX are marked [!!!] ACCEPTED
  4. Phase 2 exercises these values with actual media flow

Suggested Fix

  1. Change max_bitrate_bps from std::optional<int> to std::optional<uint32_t>
  2. OR add range validation in Blink→WebRTC conversion: if (max_bitrate > INT32_MAX) reject with RangeError

Difference from CVE-2026-5912

CVE-2026-5912 is an integer overflow in SDP text parsing (ParseBandwidthLine). This finding is in the setParameters() API path, which is architecturally separate and was NOT addressed by the CVE-2026-5912 fix.

Form Field: Impact Analysis

The WebIDL unsigned long → C++ int32 type mismatch causes undefined behavior when maxBitrate values ≥ 2,147,483,648 are set via the JavaScript API.

Who can exploit: Any JavaScript running in a page with WebRTC access.

What they gain:

  1. Undefined behavior in the BitrateAllocator — compiler may optimize away subsequent safety checks
  2. Integer overflow when summing multiple senders’ max_bitrate values
  3. Combined with the setParameters(Infinity) policy bypass (separate report), provides two independent ways to corrupt bandwidth state

This is a defense-in-depth issue: the type mismatch (uint32→int32) should be fixed regardless of whether an exploitable crash results, as undefined behavior in C++ is a security anti-pattern.



#### Impact analysis

The WebIDL unsigned long to C++ int32 type mismatch causes undefined behavior when maxBitrate values &gt;= 2,147,483,648 are set via the JavaScript API.

Who can exploit: Any JavaScript running in a page with WebRTC access.

What they gain:
1. Undefined behavior in the BitrateAllocator — compiler may optimize away subsequent safety checks
2. Integer overflow when summing multiple senders' max_bitrate values (3 x 4294967295 = 12,884,901,885 — exceeds both int32 and uint32)
3. Combined with the setParameters(Infinity) policy bypass (separate report), provides two independent ways to corrupt bandwidth state

This is a defense-in-depth issue: the type mismatch (uint32 to int32) should be fixed regardless of whether an exploitable crash results, as undefined behavior in C++ is a security anti-pattern.



---

### The cause


#### What version of Chrome have you found the security issue in?

146.0.0.0 [stable] + 147.0.7727.55 [stable]


#### Is the security issue related to a crash?

No, it is not related to a crash.


#### Choose the type of vulnerability

Other


#### How would you like to be publicly acknowledged for your report?

Ashutosh
View on issue tracker