Medium watch ✔︎ verified CVSS 8.8 chrome Integer Overflow 🔧 Commit mapped

Overview

Medium
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInteger overflow in WebGL
DescriptionInteger overflow in WebGL
ComponentWebGL
Sub-componentWebGL
Bug ClassInteger Overflow
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety — revised by independent review by AI
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.
Independent review by AIConfirmed (tier revised from patch-now)
Reviewer notes: Mechanism matches the diff, but the diff only shows a Blink-side counter underflow bypassing the linkProgram guard (now CHECK-guarded); the 'corruption' primitive and path toward renderer memory corruption are not demonstrated, so patch-now tier is overstated.
A second, independent AI reviewer (not a human) re-derived this analysis from the fixing commit and the vendor advisory, looking for errors.
Tracker513760788
Fix commit03c1c9015ca0 (chromium/src) +6/-2
CWECWE-190 (Integer overflow)
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-05-16 (per vendor advisory)
Fix landed2026-07-17 (public git)
Disclosed2026-08-25
Patch gap39 days — fix public in source before the advisory

Background

Transform feedback
a WebGL 2.0 feature that captures vertex-shader outputs into buffer objects; a program must be flagged active while it participates, via WebGLProgram::active_transform_feedback_count_.
`current_program_`
the currently bound program (set by useProgram), which per WebGL 2.0 may be swapped while transform feedback is paused, so it need not equal the program that began transform feedback.
`transform_feedback_binding_`
the bound WebGLTransformFeedback object, which independently records the program that actually started transform feedback via GetProgram().
`active_transform_feedback_count_`
an unsigned counter guarding safety checks in linkProgram; decrementing it below 0 wraps to UINT_MAX (4294967295).

Root Cause Analysis

WebGL2RenderingContextBase::endTransformFeedback called current_program_->DecreaseActiveTransformFeedbackCount(), assuming the program bound at end time was the one that started transform feedback. WebGL 2.0 permits useProgram to change current_program_ while transform feedback is paused, so at endTransformFeedback time current_program_ can point to a different program than the one whose count was incremented in beginTransformFeedback. The decrement therefore lands on the wrong WebGLProgram. Because active_transform_feedback_count_ is unsigned and initialized to 0, decrementing a program that never had its count raised underflows to UINT_MAX. Meanwhile the program that truly began transform feedback keeps a stale nonzero count, and the wrongly-decremented program now falsely appears to have a huge active count. The corrupted counter defeats linkProgram’s guard that forbids relinking a program still active in transform feedback.
Key insight
The active-transform-feedback count must be charged against the program recorded by the transform-feedback object (transform_feedback_binding_->GetProgram()), not whatever program happens to be bound at end time, because useProgram can decouple the two while paused.

Attack Path

  1. Begin feedback Bind a transform-feedback object and call beginTransformFeedback with program A, incrementing A’s count and recording A in transform_feedback_binding_.
  2. Pause and swap Call pauseTransformFeedback, then useProgram(B) so current_program_ becomes program B while A remains the feedback program.
  3. End against wrong program Call endTransformFeedback, which decrements B’s count; since B was never started, B’s active_transform_feedback_count_ underflows to UINT_MAX.
  4. Bypass link guard Relink or otherwise operate on program A (whose count is now falsely stale) or exploit B’s bogus count to slip past linkProgram safety checks while a program is effectively active in transform feedback.

Impact Assessment

The unsigned underflow corrupts active_transform_feedback_count_, letting linkProgram safety checks be bypassed while a program is active in transform feedback, which can drive the GL backend into an inconsistent state. This is an integer-overflow bug in WebGL reachable from untrusted web content and forms a primitive toward memory corruption in the renderer.

Files Changed

  • third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
  • third_party/blink/renderer/modules/webgl/webgl_program.cc

Audit Directions

  • Wrong-object accounting across pause/resume
    Audit any counter or ref incremented in a begin/start path and decremented in the matching end/stop path where the target object (here current_program_ vs transform_feedback_binding_->GetProgram()) can change in between via state-setters like useProgram.
  • Unsigned decrements without floor checks
    Search WebGL/GPU code for --count or Decrease*Count on unsigned members lacking a CHECK_GT(x, 0u) guard, since these wrap to UINT_MAX and defeat downstream validation.
  • Guards keyed on corruptible counts
    Review safety checks like linkProgram’s active-transform-feedback guard that trust a mutable count; confirm the count cannot be desynchronized from the actual active state through legal API reordering.
From 03c1c9015ca0e22259104d9099812d332d6e009d Mon Sep 17 00:00:00 2001
From: Le Hoang Quyen <lehoangquyen@chromium.org>
Date: Fri, 17 Jul 2026 09:28:04 -0700
Subject: [PATCH] [webgl] Fix transform feedback program counter underflow

In WebGL2RenderingContextBase::endTransformFeedback, when transform
feedback ends, Blink previously decremented the active transform
feedback count of current_program_. However, per the WebGL 2.0
specification, useProgram can change current_program_ while transform
feedback is paused.

If current_program_ was swapped while transform feedback was paused,
endTransformFeedback incorrectly decremented current_program_ instead
of the program associated with the transform feedback object. Because
active_transform_feedback_count_ is unsigned and initialized to 0,
decrementing a program that was never started caused an underflow to
UINT_MAX (4294967295), which could be leveraged to bypass linkProgram
safety checks while a program is active in transform feedback.

This patch updates endTransformFeedback to decrement the counter on
transform_feedback_binding_->GetProgram(), and adds a CHECK_GT in
WebGLProgram::DecreaseActiveTransformFeedbackCount to guard against
underflows.

Bug: 513760788
Change-Id: I8881c16783399255d796f3f4a35ac83fcefd2679
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8107215
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Auto-Submit: Quyen Le <lehoangquyen@google.com>
Cr-Commit-Position: refs/heads/main@{#1663963}
---
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
index 40ea7b6..1e2b512 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
@@ -4214,8 +4214,10 @@
 
   transform_feedback_binding_->SetPaused(false);
   transform_feedback_binding_->SetActive(false);
-  if (current_program_)
-    current_program_->DecreaseActiveTransformFeedbackCount();
+  if (transform_feedback_binding_->GetProgram()) {
+    transform_feedback_binding_->GetProgram()
+        ->DecreaseActiveTransformFeedbackCount();
+  }
 }
 
 void WebGL2RenderingContextBase::transformFeedbackVaryings(
diff --git a/third_party/blink/renderer/modules/webgl/webgl_program.cc b/third_party/blink/renderer/modules/webgl/webgl_program.cc
index 33698c3..f5d8c36e 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_program.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_program.cc
@@ -25,6 +25,7 @@
 
 #include "third_party/blink/renderer/modules/webgl/webgl_program.h"
 
+#include "base/check_op.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "third_party/blink/renderer/modules/webgl/webgl_context_object_support.h"
 #include "third_party/blink/renderer/modules/webgl/webgl_shader.h"
@@ -86,6 +87,7 @@
 }
 
 void WebGLProgram::DecreaseActiveTransformFeedbackCount() {
+  CHECK_GT(active_transform_feedback_count_, 0u);
   --active_transform_feedback_count_;
 }
 
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.