Medium chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in ANGLE
DescriptionUninitialized Use in ANGLE
ComponentANGLE
Bug ClassUninitialized Memory
Tracker504820809
Fix commit9f099a5d233f (angle/angle) +5/-0
CISA KEVNot listed
CreditedMufeed VH from Winfunc Research (winfunc.com)
Disclosed2026-06-02

Files Changed

  • src/libANGLE/renderer/gl/BlitGL.cpp
  • src/tests/gl_tests/RobustResourceInitTest.cpp
From 9f099a5d233f7c311d0f3d3651365e0979fcba91 Mon Sep 17 00:00:00 2001
From: Geoff Lang <[email protected]>
Date: Wed, 22 Apr 2026 13:28:09 -0400
Subject: [PATCH] GL: Set stencil write mask before clearing for robust init

Fixed: chromium:504820809
Change-Id: I45f2746e3e4e239d9bf72219330484349d441723
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7785196
Reviewed-by: Shahbaz Youssefi <[email protected]>
---

diff --git a/src/libANGLE/renderer/gl/BlitGL.cpp b/src/libANGLE/renderer/gl/BlitGL.cpp
index 0fec270..8d590ae 100644
--- a/src/libANGLE/renderer/gl/BlitGL.cpp
+++ b/src/libANGLE/renderer/gl/BlitGL.cpp
@@ -157,6 +157,7 @@
     }
     if (stencilClear)
     {
+        stateManager->setStencilFrontWritemask(static_cast<GLuint>(-1));
         stateManager->setClearStencil(0);
         *outClearMask |= GL_STENCIL_BUFFER_BIT;
     }
diff --git a/src/tests/gl_tests/RobustResourceInitTest.cpp b/src/tests/gl_tests/RobustResourceInitTest.cpp
index 340bdcd..1e05ed0 100644
--- a/src/tests/gl_tests/RobustResourceInitTest.cpp
+++ b/src/tests/gl_tests/RobustResourceInitTest.cpp
@@ -2214,6 +2214,10 @@
     };
 
     maskedStencilClear(clearFunc);
+
+    // Run the test twice. This is a regression test for state synchronization leaking into the
+    // clear operation.
+    maskedStencilClear(clearFunc);
 }
 
 // Test that clearing a masked stencil buffer doesn't mark it clean, with ClearBufferi.
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/src/tests/gl_tests/RobustResourceInitTest.cpp b/src/tests/gl_tests/RobustResourceInitTest.cpp
index 340bdcd..1e05ed0 100644
--- a/src/tests/gl_tests/RobustResourceInitTest.cpp
+++ b/src/tests/gl_tests/RobustResourceInitTest.cpp
@@ -2214,6 +2214,10 @@
     };
 
     maskedStencilClear(clearFunc);
+
+    // Run the test twice. This is a regression test for state synchronization leaking into the
+    // clear operation.
+    maskedStencilClear(clearFunc);
 }
 
 // Test that clearing a masked stencil buffer doesn't mark it clean, with ClearBufferi.
Loading diff…

Original Bug Report

reported by [email protected]

WebGL can disclose stale stencil contents because ANGLE robust framebuffer initialization honors attacker-controlled stencilMask(0)

Security Bug

VULNERABILITY DETAILS

ANGLE’s OpenGL robust-resource-initialization path can preserve stale stencil contents because the internal clear helper in BlitGL::SetClearState() sets glClearStencil(0) but never restores the front/back stencil write masks to all-ones before the later glClear(GL_STENCIL_BUFFER_BIT).

On the GL backend, FramebufferGL::ensureAttachmentsInitialized() routes first-use attachment initialization through BlitGL::clearFramebuffer(). If attacker-controlled WebGL state has already latched stencilMask(0) into the underlying GL state machine, the internal stencil clear can be suppressed while ANGLE still marks the attachment initialized. A later stencil-tested draw can then turn the stale stencil bits into script-readable color output.

The sink is still present in current source:

if (stencilClear)
{
    stateManager->setClearStencil(0);
    *outClearMask |= GL_STENCIL_BUFFER_BIT;
}

Source references:

  • third_party/angle/src/libANGLE/context_private_call.inl.h
  • third_party/angle/src/libANGLE/State.cpp
  • third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
  • third_party/angle/src/libANGLE/Framebuffer.cpp
  • third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
  • third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp

The attached browser PoC primes a fresh DEPTH24_STENCIL8 renderbuffer with stencil value 1, deletes it, syncs stencilMask(0) on a separate initialized framebuffer, then allocates a new depth-stencil attachment and triggers robust initialization on first use. It finally uses stencil-tested drawing plus readPixels() to detect non-zero stale stencil state.

On the latest Chromium main tip I synced for this validation pass, the browser leak is immediate. Importantly, on this Linux/NVIDIA system it reproduces without any backend-forcing flags such as --use-gl=angle, --use-angle=gl, or --ignore-gpu-blocklist; Chromium’s default startup path still selects ANGLE (NVIDIA Corporation, NVIDIA L4/PCIe/SSE2, OpenGL 4.5.0) for WebGL on this machine. The first attempted victim allocation already produced sum(red)=4177920, which is the full 128 x 128 x 255 frame, meaning the primed all-ones stencil pattern survived robust initialization intact.

VERSION

Chrome Version: Chromium 149.0.7804.0 + dev (local ASan build from commit edf6e4e6f9d6427ecb954106f5b889f94c30de88)

Operating System: Ubuntu 22.04.5 LTS x86_64

GPU / GL renderer: ANGLE (NVIDIA Corporation, NVIDIA L4/PCIe/SSE2, OpenGL 4.5.0) on desktop Linux

REPRODUCTION CASE

Attachments:

  • poc.html
  • stencil_browser_default_no_backend_flags_14978040.log

Numbered repro steps:

  1. Use a Chromium build configured to run WebGL through ANGLE’s GL backend on a real GPU-backed X server.
  2. Serve the attached PoC locally:
python3 -m http.server 8000
  1. Run Chromium directly. The following command includes only convenience flags for profile/log hygiene; it does not force a specific GL backend:
out/asan/chrome \
  --user-data-dir=/tmp/chrome-stencil-poc \
  --no-first-run \
  --disable-background-networking \
  --disable-default-apps \
  --disable-sync \
  --metrics-recording-only \
  --enable-logging=stderr \
  'http://127.0.0.1:8000/poc.html?iters=2000&logEvery=50&test=nonzero'

Observed result:

[poc] UNMASKED_RENDERER_WEBGL=ANGLE (NVIDIA Corporation, NVIDIA L4/PCIe/SSE2, OpenGL 4.5.0)
[poc] sync FBO prepared
[poc] LEAK observed iteration=0 sum(red)=4177920

The attached poc.html also supports the exact stencilFunc(EQUAL, 1, 0xFF) mode from the minimal write-up, but the attached browser run uses the broader NOTEQUAL, 0 detection mode to maximize reliability when validating reused stencil contents.

Type of crash: N/A (stale stencil disclosure; no crash required)

Crash State:

N/A

Client ID (if relevant): N/A

CREDIT INFORMATION

Reporter credit: Mufeed VH from Winfunc Research (winfunc.com)

View on issue tracker