CVE-2026-87452
Overview
Background
- Passthrough command decoder
- The
GLES2DecoderPassthroughimplementation ingles2_cmd_decoder_passthrough.ccthat forwards WebGL/GLES2 command-buffer calls to ANGLE with minimal translation. - `GL_TEXTURE_RECTANGLE_ANGLE`
- An ANGLE texture-target capability the GPU process uses internally for WebGL contexts but does not expose to untrusted client code.
- `IsIgnoredCap()`
- A decoder helper that decides whether a capability requested via
Enable/Disablecommand-buffer commands should be silently ignored (treated asGL_INVALID_ENUM) rather than passed through to the driver. - `ScopedEnableTextureRectangleInShaderCompiler`
- A scoped helper that transiently re-enables
GL_TEXTURE_RECTANGLE_ANGLEaround internal shader compiles after it was disabled at context initialization.
Root Cause Analysis
For WebGL contexts, the passthrough decoder deliberately disables GL_TEXTURE_RECTANGLE_ANGLE at context init and only re-enables it internally, transiently, via ScopedEnableTextureRectangleInShaderCompiler around its own shader compiles. The invariant is that this capability must never be controllable by the client renderer, since it is internal-only and blocked in ANGLE for WebGL.
Before the fix, IsIgnoredCap() did not list GL_TEXTURE_RECTANGLE_ANGLE, so an Enable or Disable command carrying that enum fell through to the default branch (returning false) and was forwarded to the driver instead of being rejected. This let a compromised renderer toggle an internal-only capability out from under the decoder’s controlled scoping, an authorization gap in the command-buffer surface.
The fix adds a case GL_TEXTURE_RECTANGLE_ANGLE that returns feature_info_->IsWebGLContext(), causing the command to be ignored and to raise GL_INVALID_ENUM for WebGL/WebGPU-style contexts, restoring the invariant that only internal code manages this state.
GL_TEXTURE_RECTANGLE_ANGLE) from the IsIgnoredCap() allow/deny list, leaving it client-reachable through Enable/Disable. The fix closes the gap by treating the capability as ignored for WebGL contexts so the command buffer rejects it with GL_INVALID_ENUM instead of forwarding it.Attack Path
- Compromise the renderer An attacker first gains code execution in a renderer/GPU-client process, giving control over the raw command-buffer stream.
- Craft an Enable command
The attacker emits an
Enable(orDisable) command-buffer command with the internal-only enumGL_TEXTURE_RECTANGLE_ANGLE. - Bypass the decoder check
Because
IsIgnoredCap()did not cover this enum, the decoder passes it through to ANGLE/the driver rather than rejecting it. - Toggle internal-only state
The attacker enables or disables the texture-rectangle capability outside the decoder’s controlled
ScopedEnableTextureRectangleInShaderCompilerscoping, violating the intended internal-only usage.
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fgpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc |
modified |
Files Changed
gpu/command_buffer/service/gles2_cmd_decoder_passthrough.ccgpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc
Audit Directions
- Internal-only capability leakageAudit every capability the GPU process manages internally (via scoped helpers like
ScopedEnableTextureRectangleInShaderCompiler) and confirm each is also listed inIsIgnoredCap()so it cannot be toggled through clientEnable/Disablecommands. - Enum allow-list completenessReview
switchstatements with a permissivedefault: return false;in command-buffer validation paths for missing internal-only enums that silently fall through to the driver. - Context-type gatingVerify that internal-only state is gated on the correct context type (
IsWebGLContext()and equivalent WebGPU checks) so a compromised renderer cannot reach it via a different context type than the one it was scoped for.
Patch
From fc0834fae837a6f60c86d2fb04febd191824307c Mon Sep 17 00:00:00 2001 From: Brandon Jones <[email protected]> Date: Thu, 06 Aug 2026 15:21:41 -0700 Subject: [PATCH] Reject GL_TEXTURE_RECTANGLE_ANGLE for WebGL contexts The passthrough decoder uses GL_TEXTURE_RECTANGLE_ANGLE internally for WebGL contexts via ScopedEnableTextureRectangleInShaderCompiler, disabling it at context init and re-enabling it only around internal shader compiles. Adding to IsIgnoredCap() so a compromised renderer cannot enable it with a WebGPU context. Bug: 513524705 Change-Id: I9f45058a1a915edbe1b6d7af6fa36669f1c5dd1d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8168700 Reviewed-by: Zhenyao Mo <[email protected]> Commit-Queue: Brandon Jones <[email protected]> Cr-Commit-Position: refs/heads/main@{#1675334} --- diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index 8cbf7ae..7fa98ea 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc @@ -2207,6 +2207,10 @@ // it's blocked in ANGLE for WebGL contexts. return feature_info_->IsWebGLContext(); + case GL_TEXTURE_RECTANGLE_ANGLE: + // Used internally, not exposed to WebGL contexts. + return feature_info_->IsWebGLContext(); + default: return false; } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc index 6073234b..6bb7fac4 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc @@ -153,5 +153,22 @@ GLES2DecoderPassthroughImmediateSizeArgCommandTest, ES3ImmediateSizeArgCommandTypes0); +// GL_TEXTURE_RECTANGLE_ANGLE is only for internal use and should not be +// reachable through the command buffer. +TEST_F(GLES2WebGLDecoderPassthroughTest, EnableDisableTextureRectangle) { + { + cmds::Enable cmd; + cmd.Init(GL_TEXTURE_RECTANGLE_ANGLE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + } + { + cmds::Disable cmd; + cmd.Init(GL_TEXTURE_RECTANGLE_ANGLE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + } +} + } // namespace gles2 } // namespace gpu
Regression Test / PoC
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc
index 6073234b..6bb7fac4 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc
@@ -153,5 +153,22 @@
GLES2DecoderPassthroughImmediateSizeArgCommandTest,
ES3ImmediateSizeArgCommandTypes0);
+// GL_TEXTURE_RECTANGLE_ANGLE is only for internal use and should not be
+// reachable through the command buffer.
+TEST_F(GLES2WebGLDecoderPassthroughTest, EnableDisableTextureRectangle) {
+ {
+ cmds::Enable cmd;
+ cmd.Init(GL_TEXTURE_RECTANGLE_ANGLE);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+ }
+ {
+ cmds::Disable cmd;
+ cmd.Init(GL_TEXTURE_RECTANGLE_ANGLE);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+ }
+}
+
} // namespace gles2
} // namespace gpu
Original Bug Report
Potential hardening bypass: Compromised renderer can re-enable GL_TEXTURE_RECTANGLE_ANGLE on macOS
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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: The GLES2 passthrough command decoder on macOS fails to block the GL_TEXTURE_RECTANGLE_ANGLE capability in its Enable command handler. A compromised renderer can potentially re-enable this internal-only capability to use restricted rectangle textures in WebGL shaders, bypassing a defense-in-depth measure.
Affected files:
gpu/command_buffer/service/gles2_cmd_decoder_passthrough.ccgpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
Estimated timestamp from git blame: 2020-01-30
Description
On macOS, Chromium uses the GL_TEXTURE_RECTANGLE_ANGLE capability internally to support IOSurface-backed textures. To prevent WebGL user shaders from accessing these textures, Chromium implements a hardening measure by explicitly disabling this capability for WebGL contexts during initialization. This isolation is enforced by the ANGLE shader translator, which blocks the ARB_texture_rectangle extension if the capability is disabled.
However, the passthrough command decoder’s DoEnable handler does not sufficiently filter this capability. The handler relies on IsIgnoredCap to block restricted enums, but IsIgnoredCap lacks an entry for GL_TEXTURE_RECTANGLE_ANGLE. Since ANGLE allows this capability to be toggled for WebGL contexts, a compromised renderer can re-enable it via a standard glEnable command.
Technical Details
In gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc, the capability is disabled at initialization for WebGL contexts:
#if BUILDFLAG(IS_MAC)
if (feature_info_->IsWebGLContext())
api()->glDisableFn(GL_TEXTURE_RECTANGLE_ANGLE);
#endif
The DoEnable implementation in gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc validates capabilities using IsIgnoredCap:
error::Error GLES2DecoderPassthroughImpl::DoEnable(GLenum cap) {
if (IsIgnoredCap(cap)) {
InsertError(GL_INVALID_ENUM, "Invalid cap.");
return error::kNoError;
}
api()->glEnableFn(cap);
return error::kNoError;
}
The IsIgnoredCap function in gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc fails to include GL_TEXTURE_RECTANGLE_ANGLE (0x84F5), allowing it to fall through to the default return false case. This allows the glEnable call to reach ANGLE.
Impact
By re-enabling GL_TEXTURE_RECTANGLE_ANGLE, the ANGLE shader translator will no longer set the disableARBTextureRectangle compiler option. This allows a compromised renderer to compile and execute shaders that use #extension GL_ARB_texture_rectangle : enable and sampler2DRect types. This represents a bypass of a hardening layer designed to isolate WebGL from internal macOS texture types.
Potential Steps to Reproduce
These steps are based on code analysis and represent a potential attack vector:
- From a compromised renderer process on macOS (using the ANGLE OpenGL backend), send a
gles2::cmds::Enablecommand withcap = 0x84F5(GL_TEXTURE_RECTANGLE_ANGLE). - Send a
ShaderSourcecommand containing GLSL code that attempts to use theGL_ARB_texture_rectangleextension. - Send a
CompileShadercommand and observe that the shader compiles successfully. - In a debug build, subsequent internal usage of
ScopedEnableTextureRectangleInShaderCompilermay trigger aDCHECKinui/gl/gl_utils.ccbecause the capability is unexpectedly already enabled.
Suggested Fix
Modify GLES2DecoderPassthroughImpl::IsIgnoredCap in gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc to include GL_TEXTURE_RECTANGLE_ANGLE, ensuring it returns true (or at least feature_info_->IsWebGLContext()) to block the renderer from toggling this state.
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.