CVE-2026-13920
Overview
Files Changed
media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
Patch
From cce48a3af72af9fe06ce9c1bba0ed6e197be617a Mon Sep 17 00:00:00 2001
From: Eugene Zemtsov <eugene@chromium.org>
Date: Tue, 12 May 2026 11:09:08 -0700
Subject: [PATCH] media: Validate arguments for CopySubresourceRegion and VideoProcessorBlt
This change adds bounds validation in MediaFoundationVideoEncodeAccelerator
(PerformD3DCopy and PerformD3DScaling) to ensure the untrusted
`visible_rect` does not exceed the actual D3D11 texture dimensions.
Bug: 511722559
Change-Id: I6a71136293c85b362e570f2184436cffcb7ea8a0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7839078
Reviewed-by: Qiu, Jianlin <jianlin.qiu@intel.com>
Commit-Queue: Eugene Zemtsov <eugene@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1629457}
---
diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
index 959010d..78d7396 100644
--- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
+++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
@@ -2872,6 +2872,17 @@
D3D11_TEXTURE2D_DESC input_texture_desc = {};
input_texture->GetDesc(&input_texture_desc);
+
+ if (visible_rect.x() < 0 || visible_rect.y() < 0 ||
+ visible_rect.right() > static_cast<int>(input_texture_desc.Width) ||
+ visible_rect.bottom() > static_cast<int>(input_texture_desc.Height)) {
+ LOG(ERROR) << "Source visible_rect " << visible_rect.ToString()
+ << " is out of bounds for texture of size "
+ << input_texture_desc.Width << "x"
+ << input_texture_desc.Height;
+ return E_INVALIDARG;
+ }
+
RECT source_rect = {static_cast<LONG>(visible_rect.x()),
static_cast<LONG>(visible_rect.y()),
static_cast<LONG>(visible_rect.right()),
@@ -2967,6 +2978,18 @@
release_keyed_mutex.emplace(std::move(keyed_mutex), 0);
}
+ D3D11_TEXTURE2D_DESC input_desc;
+ input_texture->GetDesc(&input_desc);
+
+ if (visible_rect.x() < 0 || visible_rect.y() < 0 ||
+ visible_rect.right() > static_cast<int>(input_desc.Width) ||
+ visible_rect.bottom() > static_cast<int>(input_desc.Height)) {
+ LOG(ERROR) << "Source visible_rect " << visible_rect.ToString()
+ << " is out of bounds for texture of size " << input_desc.Width
+ << "x" << input_desc.Height;
+ return E_INVALIDARG;
+ }
+
D3D11_BOX src_box = {static_cast<UINT>(visible_rect.x()),
static_cast<UINT>(visible_rect.y()),
0,
Original Bug Report
Potential OOB GPU memory read in MFVideoEncodeAccelerator via forged SharedImage size
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 Chrome Security team. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: A compromised renderer can forge the size metadata of an ExportedSharedImage, which is trusted by the GPU process without validation against the underlying DXGI handle. This allows an attacker to pass an out-of-bounds source rectangle to D3D11 operations in the MediaFoundationVideoEncodeAccelerator. This can potentially result in an out-of-bounds read of adjacent GPU memory, which is encoded and leaked back to the renderer.
Affected files:
media/gpu/windows/media_foundation_video_encode_accelerator_win.ccmedia/mojo/services/mojo_video_encode_accelerator_service.ccgpu/command_buffer/client/client_shared_image.ccgpu/command_buffer/client/internal/mappable_buffer_dxgi.ccmedia/base/video_frame.ccmedia/mojo/mojom/video_frame_mojom_traits.cc
Estimated timestamp from git blame: 2025-09-04
Description
A potential vulnerability exists in the Media Foundation Video Encode Accelerator (MFVEA) on Windows where a compromised renderer can cause an out-of-bounds (OOB) read of GPU memory. The issue occurs because the GPU process trusts the metadata.size of an ExportedSharedImage over IPC without verifying it against the actual dimensions of the underlying DXGI resource.
This unvalidated size bypasses encoder validation checks, allowing an oversized visible_rect to be used when building source regions for D3D11 scaling and copy operations. Because the D3D11 driver is instructed to read beyond the bounds of the actual allocation, it may access adjacent GPU memory.
Potential Attacker Steps
Although an end-to-end proof of concept has not been executed, tracing the code suggests the following sequence of events could trigger the vulnerability:
- Resource Creation: A compromised renderer process creates a small, valid DXGI-backed
SharedImage(e.g., 64x64 pixels) and obtains its underlying OS handle (gfx::GpuMemoryBufferHandle). - Metadata Forgery: The renderer constructs a malicious
media::mojom::VideoFrameto send to the GPU process. In theExportedSharedImagepayload, it includes the valid OS handle but forgesmetadata.size,coded_size, andvisible_rectto a much larger dimension (e.g., 8192x8192). - Missing Validation on Import: The GPU process deserializes the frame. In
gpu/command_buffer/client/internal/mappable_buffer_dxgi.cc,CreateFromHandlewraps the DXGI handle without querying the OS to ensure the texture is actually as large as the providedsize. - Encoder Check Bypass: The
VideoFrameadopts the forged dimensions. When it reachesMojoVideoEncodeAcceleratorService::Encode, it bypasses theinput_coded_size_mismatch check becauseframe->HasMappableSharedImage()evaluates to true. - OOB D3D11 Operation: The frame reaches
MediaFoundationVideoEncodeAccelerator.- In
PerformD3DScaling, the code correctly queries the actual texture dimensions viainput_texture->GetDesc(). However, it ignores these dimensions, blindly constructing aRECT source_rectusing the attacker-controlledvisible_rect. - This oversized
source_rectis passed toVideoProcessorSetStreamSourceRectand executed viaVideoProcessorBlt. - (Alternatively, the same flaw exists in
PerformD3DCopywhere an oversizedD3D11_BOX src_boxis passed toCopySubresourceRegion).
- In
- Information Leak: The D3D11 driver executes the OOB read. The leaked GPU memory is processed, encoded into a video bitstream by the Media Foundation hardware encoder, and the compressed payload is returned to the compromised renderer.
Impact
This vulnerability potentially allows a compromised renderer process to read arbitrary GPU memory from other origins or desktop applications, resulting in a cross-origin information leak (Sandbox Escape). Providing invalid, out-of-bounds regions to D3D11 drivers might also result in memory corruption within the unsandboxed GPU process or cause the user-mode driver to crash.
Recommended Fix
- MFVEA Clamping: In
media/gpu/windows/media_foundation_video_encode_accelerator_win.cc, updatePerformD3DScalingandPerformD3DCopyto clamp thevisible_rectto the actual dimensions of the texture (obtained viaGetDesc()) before constructingsource_rectandsrc_box. - Import Validation: Consider adding validation to
MappableBufferDXGI::CreateFromHandle(similar toMappableBufferIOSurface) to query the underlying DXGI resource and reject the import if the requested size exceeds the actual resource bounds.
Evaluated with Chrome root at commit: eca8648a4e1cdfdda68c495a6003059fed641955
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.