CVE-2026-9914
Overview
Files Changed
extensions/ANGLE_yuv_internal_format.txt
Patch
From 847b036be55376e2dcae10e1d10e5b4c993f2adf Mon Sep 17 00:00:00 2001
From: Mohan Maiya <m.maiya@samsung.com>
Date: Wed, 22 Apr 2026 13:19:50 -0500
Subject: [PATCH] Update ANGLE_yuv_internal_format spec
Added clarification to allow sample-only usage of textures
Bug: chromium:500047428
Change-Id: I56a5fdf6b4502abb851e61763f3b709012c31b94
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7784198
Auto-Submit: mohan maiya <m.maiya@samsung.com>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
---
diff --git a/extensions/ANGLE_yuv_internal_format.txt b/extensions/ANGLE_yuv_internal_format.txt
index 7ae5363..2c2ba3f 100644
--- a/extensions/ANGLE_yuv_internal_format.txt
+++ b/extensions/ANGLE_yuv_internal_format.txt
@@ -26,7 +26,7 @@
Version
- Version 5, June 23, 2021
+ Version 7, April 23, 2026
Number
@@ -36,6 +36,8 @@
OpenGL ES 3.0 is required.
+ This extension interacts with GL_EXT_YUV_target, see issue 4
+
Overview
This extension introduces a few sized internal YUV texture formats
@@ -96,8 +98,43 @@
for textures with the above YUV formats is assumed to be ITU-R BT.601 with YUV
values in limited range. Refer to ITU-R BT.601 spec for further details.
+ 3. Can textures created with these new formats be rendered to via color attachments?
+
+ No, this extension only allows for sampling from such textures. This means attaching
+ textures created using ANGLE_yuv_internal_format as framebuffer color attachments is
+ invalid and the framebuffer completeness check fails with a
+ FRAMEBUFFER_INCOMPLETE_ATTACHMENT error.
+
+ Some additional context - GLES has no native support for YUV formats. Support for
+ usecases that need to sample from YUV formats, like camera and video, is achieved
+ through a multi-step process of creating EGLImages backed by "external memory" and
+ binding them to external texture targets.
+
+ On Android, for example, an app can create an Android Hardware Buffer (AHB) with a
+ YUV format, create an EGLImage out of it using EGL_ANDROID_image_native_buffer,
+ bind the image to an external texture target using GL_OES_EGL_image_external and then
+ sample from that texture. This severely limits validation of YUV features to only
+ those platforms that support all these extensions (or their equivalents).
+
+ The intent behind ANGLE_yuv_internal_format extension is to decouple YUV code paths
+ from EGLImages and "external memory" in ANGLE when using the Vulkan backend
+ (since Vulkan is capable of supporting YUV formats natively).
+
+ 4. How does this extension interact with EXT_YUV_target?
+
+ EXT_YUV_target extension provides 2 categories of enhancements - raw YUV sampling
+ from textures and rendering to YUV textures, only the former is relevant to
+ ANGLE_yuv_internal_format. It is valid to sample raw YUV values from a texture
+ created using ANGLE_yuv_internal_format
+
Revision History
+ #7 - (April 23, 2026) Mohan Maiya
+ Clarify interaction with EXT_YUV_target
+
+ #6 - (April 22, 2026) Mohan Maiya
+ Clarification about sample-only usage of textures
+
#5 - (June 23, 2021) Mohan Maiya
Renamed format enums from *_ANGLEX to *_ANGLE
Original Bug Report
Validation Bypass and VUID Violation via Native YUV Textures in ANGLE
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 without the security team.
Overview: A potential vulnerability exists where native YUV textures bypass validation due to a missing isYUV() override in gl::Texture. A compromised renderer can pass an arbitrary YUV format to the passthrough decoder, causing ANGLE to send malformed multi-planar commands to the Vulkan backend. This results in undefined driver behavior and potential GPU process memory corruption.
Affected files:
third_party/angle/src/libANGLE/Texture.hthird_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.hthird_party/angle/src/libANGLE/Texture.cppthird_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cppthird_party/angle/src/libANGLE/Image.cppthird_party/angle/src/libANGLE/validationES.cppthird_party/angle/src/libANGLE/Framebuffer.cpp
Estimated timestamp from git blame: 2023-10-17
Description
A potential vulnerability exists in how ANGLE handles native YUV textures (e.g., GL_G8_B8R8_2PLANE_420_UNORM_ANGLE), allowing a compromised renderer to bypass validation and trigger undefined behavior in the GPU process via Vulkan API violations. This relies on three chained flaws in the GPU process:
- Passthrough Decoder Validation Bypass: The
GLES2DecoderPassthroughImplblindly forwards theinternalformatargument of commands likeTexStorage2DEXTdirectly to ANGLE without validating it against Chrome’svalidators_.texture_internal_format_storage. A compromised renderer can manually construct an IPC to submit arbitrary internal formats. - Missing
gl::Texture::isYUV()Override:gl::Textureinherits fromegl::ImageSiblingbut does not override the virtualisYUV()method. The defaultegl::ImageSibling::isYUV()implementation returnsfalseunless the texture is an EGLImage target (mTargetOf). Native YUV textures created viaglTexStorage2DEXThave a nullmTargetOf, causingisYUV()to incorrectly returnfalse. This causes ANGLE validation functions (e.g.,ValidateCopyTexImageParametersBase) to treat the texture as a standard color format and bypassGL_INVALID_OPERATIONerrors for YUV-restricted operations. - Vulkan Backend Format Misidentification: In the Vulkan backend (e.g.,
ImageHelper::readPixelsImpl), ANGLE checks if a texture requires YUV-to-RGBA staging by evaluatinggetExternalFormat() != 0. Because native Vulkan YUV formats have an external format of0, this check fails, and the safe staging path is skipped.
When these flaws are combined, ANGLE attempts direct operations (e.g., vkCmdCopyImageToBuffer) on the multi-planar YUV image using VK_IMAGE_ASPECT_COLOR_BIT. This violates Vulkan specification requirements (VUID-vkCmdCopyImageToBuffer-srcImage-07971), resulting in undefined behavior and out-of-bounds memory accesses in the underlying graphics driver.
Potential Reproduction Steps
Note: Our tooling agent does not have the ability to run code. These are the suggested steps an attacker would follow.
- Obtain arbitrary code execution within a sandboxed renderer process.
- Write a raw
glRequestExtensionCHROMIUMIPC to the command buffer to enable theGL_ANGLE_yuv_internal_formatextension for the context. - Construct a raw
TexStorage2DEXTIPC, manually setting theinternalformatargument toGL_G8_B8R8_2PLANE_420_UNORM_ANGLE(enum value0x96B1). - Create a Framebuffer Object (FBO) and bind the native YUV texture to color attachment 0. ANGLE will report the framebuffer as
GL_FRAMEBUFFER_COMPLETE. - Trigger a command strictly prohibited for YUV framebuffers, such as
glCopyTexImage2DorglReadPixels. - Because validation is bypassed, the invalid operation reaches the Vulkan backend, passing a malformed command to the driver and triggering a potential sandbox escape.
Suggested Fix
- Override
isYUV()ingl::Texture: Implementgl::Texture::isYUV()to accurately report its state based on its internal format (e.g., checking if the base level description format has the YUV property). - Update Vulkan Backend Checks: Update the backend (e.g.,
ImageHelper::readPixelsImpl) to rely on the actual format’s YUV property (getActualFormat().isYUV) instead of strictly checking if the external format is non-zero. - Harden Passthrough Decoder: Implement validation in
GLES2DecoderPassthroughImpl::DoTexStorage2DEXTand related commands to rejectinternalformatvalues that are not explicitly permitted by Chrome’s feature info.
Evaluated with Chrome root at commit: f200f57a19490707ff8bc7aa5de3cbc443a3afad
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; 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.