Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in Dawn
DescriptionUninitialized Use in Dawn
ComponentDawn
Sub-componentCompat
Bug ClassUninitialized Memory
Action tierwatch — information disclosure — security-relevant, below the RCE-class bar
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.
Tracker516882109
Fix commitb84c4b43197d (dawn) +8/-5
CWECWE-457 (Use of uninitialized)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-05-26 (per vendor advisory)
Fix landed2026-06-23 (public git)
Disclosed2026-07-29
Patch gap36 days — fix public in source before the advisory

Background

Dawn
Chromium’s cross-platform implementation of the WebGPU API, including the OpenGL/OpenGL ES backend under src/dawn/native/opengl.
WebGPU compatibility mode
a restricted WebGPU profile targeting older GPUs that nonetheless assumes float color formats are renderable.
`GL_EXT_color_buffer_float`
an OpenGL ES extension that makes float32/float16/rg11b10ufloat textures usable as renderable color attachments.
Uninitialized use
reading memory whose contents were never validly written, here a float texture treated as renderable when the GL driver never rendered into it.

Root Cause Analysis

In PhysicalDevice::InitializeImpl, the OpenGL ES branch previously computed isFloat32Renderable, isFloat16Renderable, and isRG11B10UfloatRenderable conditionally from the GLES version and available extensions, so on an ES 3.1 device lacking GL_EXT_color_buffer_float these flags could be false. However, WebGPU compatibility mode and downstream Dawn operations assumed float color formats were always renderable, so paths like CopyTextureToTexture implemented via render/blit operated on a float texture the driver would not actually render into. Because the texture was never validly initialized by a render pass, the copy produced or read uninitialized GPU memory. The mismatch between Dawn’s assumption and the device’s real capabilities is the root cause.

The fix adds a DAWN_INVALID_IF that requires GL_EXT_color_buffer_float (or ES 3.2) at device creation, making float renderability a guaranteed precondition. With the guarantee enforced, the three flags are DAWN_ASSERTed and hardcoded to true, closing the gap between assumption and capability.

Key insight
Dawn treated a conditional device capability as if it were universally true, so a device that legitimately advertised ES 3.1 without float-renderable color buffers slipped through and let copy/blit paths touch memory the driver never initialized. Enforcing the capability at admission time turns the fragile runtime assumption into a hard precondition.

Attack Path

  1. Target a weak device Reach an ES 3.1 GPU/driver that lacks GL_EXT_color_buffer_float, where float color formats are not truly renderable.
  2. Create a compat device Obtain a WebGPU compatibility-mode device that Dawn admits despite the missing float renderability guarantee.
  3. Allocate a float texture Create a float32/float16/rg11b10ufloat texture that Dawn assumes is renderable but the driver cannot initialize via rendering.
  4. Trigger render-based copy Invoke CopyTextureToTexture (implemented via render/blit) so Dawn operates on the never-initialized float texture.
  5. Exfiltrate residue Read back the destination to recover uninitialized GPU memory contents.

Impact Assessment

An attacker running WebGPU in compatibility mode on affected ES 3.1 devices could read uninitialized GPU memory, an information-disclosure primitive that may leak residual pixel data or other GPU allocations across origins. Severity is bounded by the requirement of a specific weak GL ES configuration, but the surface is web-reachable through ordinary WebGPU calls. No memory corruption is indicated by the diff; the vulnerability is an uninitialized-use / info-leak class defect.

Files Changed

  • src/dawn/native/opengl/PhysicalDeviceGL.cpp

Audit Directions

  • Assumed-vs-actual capability
    Audit other Dawn backends and features that assume a format is renderable, copyable, or filterable without validating the device’s real GL/driver support at admission time.
  • Render-implemented copies
    Review paths like CopyTextureToTexture and blit/clear helpers that rely on rendering into a texture, ensuring the target format’s renderability is guaranteed before use.
  • Conditional-flag-to-hardcode changes
    Search for capability flags computed from version/extension checks and used as preconditions elsewhere, confirming the precondition is enforced rather than merely assumed.
From b84c4b43197dedf9e22d242270b497a138c6358c Mon Sep 17 00:00:00 2001
From: Shrek Shao <shrekshao@google.com>
Date: Tue, 23 Jun 2026 09:30:58 -0700
Subject: [PATCH] Compat: Require GL_EXT_color_buffer_float for GL device creation

Require the GL_EXT_color_buffer_float extension in
PhysicalDevice::InitializeImpl(). As it is required in
WebGPU compatibility mode spec.

Since GL_EXT_color_buffer_float is now guaranteed in compat device,
the CopyTextureToTexture vulnerability is gone.

GL_EXT_color_buffer_half_float is subset so no need checking it
anymore now.

Bug: 516882109
Change-Id: I82ca687def2cd57d8a08ed84363f2bf85b93e784
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/318275
Commit-Queue: Shrek Shao <shrekshao@google.com>
Auto-Submit: Shrek Shao <shrekshao@google.com>
Reviewed-by: Stephen White <senorblanco@chromium.org>
---

diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.cpp b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
index b597959..49d07ac 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.cpp
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
@@ -158,6 +158,9 @@
     switch (GetBackendType()) {
         case wgpu::BackendType::OpenGLES:
             DAWN_INVALID_IF(!mFunctions.IsAtLeastGLES(3, 1), "OpenGL ES 3.1 is required.");
+            DAWN_INVALID_IF(!mFunctions.IsAtLeastGLES(3, 2) &&
+                                !mFunctions.IsGLExtensionSupported("GL_EXT_color_buffer_float"),
+                            "GL_EXT_color_buffer_float is required for OpenGL ES 3.1.");
             break;
         case wgpu::BackendType::OpenGL:
             DAWN_INVALID_IF(!mFunctions.IsAtLeastGL(4, 4), "Desktop OpenGL 4.4 is required.");
@@ -443,11 +446,11 @@
     bool supportsStencilWriteTexture =
         gl.GetVersion().IsDesktop() || gl.IsGLExtensionSupported("GL_OES_texture_stencil8");
 
-    bool isFloat32Renderable = gl.GetVersion().IsDesktop() || gl.IsAtLeastGLES(3, 2) ||
-                               gl.IsGLExtensionSupported("GL_EXT_color_buffer_float");
-    bool isFloat16Renderable =
-        isFloat32Renderable || gl.IsGLExtensionSupported("GL_EXT_color_buffer_half_float");
-    bool isRG11B10UfloatRenderable = isFloat32Renderable;
+    DAWN_ASSERT(gl.GetVersion().IsDesktop() || gl.IsAtLeastGLES(3, 2) ||
+                gl.IsGLExtensionSupported("GL_EXT_color_buffer_float"));
+    bool isFloat32Renderable = true;
+    bool isFloat16Renderable = true;
+    bool isRG11B10UfloatRenderable = true;
 
     // TODO(crbug.com/dawn/343): Investigate emulation.
     deviceToggles->Default(Toggle::DisableIndexedDrawBuffers, !supportsIndexedDrawBuffers);
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential GPU memory leak on GLES 3.1 devices due to missing float format checks in T2T copies

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 texture-to-texture (T2T) copy workaround routing logic in Dawn lacks checks for float-renderability toggles. On OpenGL ES 3.1 devices where float renderability is unsupported, direct copies silently fail while the destination texture is incorrectly marked as initialized. Subsequent reads of the texture bypass lazy-clearing and expose uninitialized GPU heap memory.

Affected files:

  • third_party/dawn/src/dawn/native/CommandEncoder.cpp
  • third_party/dawn/src/dawn/native/opengl/CommandBufferGL.cpp
  • third_party/dawn/src/dawn/native/opengl/UtilsGL.cpp

Estimated timestamp from git blame: 2025-01-17

Description

There is a potential security vulnerability in Dawn’s Texture-to-Texture (T2T) copy path on OpenGL ES 3.1 devices that do not support float-renderability extensions (such as GL_EXT_color_buffer_float or GL_EXT_color_buffer_half_float).

In third_party/dawn/src/dawn/native/CommandEncoder.cpp, the function ShouldUseT2B2TForT2T determines if a copy operation must use an intermediate workaround buffer or if it can use a direct native copy. However, this function lacks checks for the following float-renderability toggles:

  • UseBlitForRG11B10UfloatTextureCopy
  • UseBlitForFloat16TextureCopy
  • UseBlitForFloat32TextureCopy

Because these toggles are not checked, ShouldUseT2B2TForT2T returns false on devices requiring float-copy workarounds, causing Dawn to attempt a direct native copy.

Mechanism of Failure

  1. When executing CopyTextureToTexture in third_party/dawn/src/dawn/native/opengl/CommandBufferGL.cpp, the destination texture subresource is marked as initialized before performing the actual copy if the copy completely covers the subresource:
    if (IsCompleteSubresourceCopiedTo(dstTexture, copySize.ToExtent3D(), dst.mipLevel, dst.aspect)) {
        dstTexture->SetIsSubresourceContentInitialized(true, dstRange);
    }
    
  2. The OpenGL backend executes CopyImageSubData in third_party/dawn/src/dawn/native/opengl/UtilsGL.cpp. On OpenGL ES 3.1 devices, it falls back to manual glBlitFramebuffer emulation using temporary framebuffers (FBOs).
  3. Attaching non-color-renderable textures to the FBO yields a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT status, causing glBlitFramebuffer to generate a GL_INVALID_FRAMEBUFFER_OPERATION error and fail silently without writing any data.
  4. In release builds, DAWN_GL_TRY compiles to direct calls without active error-checking ((gl.call)), letting the failure pass silently.
  5. The destination texture’s memory remains uninitialized, but internal tracking registers it as initialized. A subsequent readback via compute shader (T2B) samples raw, uninitialized GPU memory and transfers it to the renderer.

Potential Reproduction Steps

Note: These are suggested steps based on static analysis of the source code. Our tooling currently lacks the capability to execute live code on GLES 3.1 emulation targets.

  1. On a platform with a GLES 3.1 driver lacking float color-renderability (such as GL_EXT_color_buffer_float), obtain a WebGPU compatibility adapter.
  2. Create a destination float texture (rgba16float or rgba32float) and a source texture containing known data.
  3. Execute a copyTextureToTexture call to copy the source to the destination completely. The destination is marked as initialized, but the copy silently fails.
  4. Execute copyTextureToBuffer to read back the destination texture to a host-mappable buffer. The T2B path utilizes the compute shader blit workaround.
  5. Because the destination is marked as initialized, the lazy-clearing check is bypassed. The compute shader reads uncleared GPU memory into the buffer, leaking cross-origin GPU heap data.

Suggested Fix

Update ShouldUseT2B2TForT2T in third_party/dawn/src/dawn/native/CommandEncoder.cpp to check float-renderability toggles and return true if they are enabled for the corresponding textures:

bool ShouldUseT2B2TForT2T(const DeviceBase* device,
                          const Format& srcFormat,
                          const Format& dstFormat) {
    // ... existing checks ...

    // Float formats checks
    if ((srcFormat.format == wgpu::TextureFormat::RG11B10Ufloat &&
         device->IsToggleEnabled(Toggle::UseBlitForRG11B10UfloatTextureCopy)) ||
        ((srcFormat.format == wgpu::TextureFormat::R16Float ||
          srcFormat.format == wgpu::TextureFormat::RG16Float ||
          srcFormat.format == wgpu::TextureFormat::RGBA16Float) &&
         device->IsToggleEnabled(Toggle::UseBlitForFloat16TextureCopy)) ||
        ((srcFormat.format == wgpu::TextureFormat::R32Float ||
          srcFormat.format == wgpu::TextureFormat::RG32Float ||
          srcFormat.format == wgpu::TextureFormat::RGBA32Float) &&
         device->IsToggleEnabled(Toggle::UseBlitForFloat32TextureCopy))) {
        return true;
    }

    return false;
}

Evaluated with Chrome root at commit: b1520ef4a76878853a31f0943b565e42060edec8


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.

View on issue tracker