Medium watch ✔︎ verified CVSS 7.5 chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
7.5
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Media
DescriptionInappropriate implementation in Media
ComponentMedia
Sub-componentMFVEA
Bug ClassLogic Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety — factors set by independent review by AI
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.
Independent review by AIConfirmed
Reviewer notes: none. Citations verified: UpdateFrameSize 1098-1170, DCHECK(pending_input_queue_.empty()) at 1106, input_visible_size_=frame_size 1113, MFT reconfigure 1123-1167; diff replaces DCHECK with runtime NotifyErrorStatus/return. Downstream OOB read in vendor MFT correctly inferred.
A second, independent AI reviewer (not a human) re-derived this analysis from the fixing commit and the vendor advisory, looking for errors.
Tracker499052720
Fix commit65ff0534249f (chromium/src) +9/-1
CWECWE-693
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-04-02 (per vendor advisory)
Fix landed2026-04-03 (public git)
Disclosed2026-05-12
Patch gap39 days — fix public in source before the advisory

Background

`MediaFoundationVideoEncodeAccelerator`
the Windows GPU-process video encoder wrapping a Media Foundation Transform (MFT).
`UpdateFrameSize`
the method that reconfigures the MFT and input_visible_size_ when the requested encode resolution changes.
`pending_input_queue_`
the queue of input frames already accepted but not yet handed to the MFT.
`DCHECK`
a debug-only assertion that is compiled out of release builds.
`NotifyErrorStatus`
the accelerator’s call that reports a fatal EncoderStatus and stops further processing.

Root Cause Analysis

In the pre-fix UpdateFrameSize (media/gpu/windows/media_foundation_video_encode_accelerator_win.cc:1098-1170), the only check that the input queue was empty before reconfiguring was a debug assertion, DCHECK(pending_input_queue_.empty()) at line 1106. The method then proceeded to set input_visible_size_ = frame_size at line 1113 and reconfigure the MFT for the new dimensions (the ProcessMessage/SetInputType/SetOutputType/MFSetAttributeSize sequence at lines 1123-1167). The invariant is “the input queue must be empty when the frame size changes, so no frame sized for the old resolution is later fed to an MFT configured for a new one.” Because DCHECK is compiled out of release builds, that invariant was unenforced in shipping Chrome: a frame-size change requested while frames were still queued would proceed, leaving stale, differently-sized samples in pending_input_queue_.

The fix replaces the DCHECK with a real runtime guard — if (!pending_input_queue_.empty()) { NotifyErrorStatus({EncoderStatus::Codes::kEncoderIllegalState, "Can't change frame size when there are pending input frames"}); return; } — so an unexpected non-empty queue now fails the encode cleanly instead of reconfiguring. This TIGHTENS the code by promoting a debug assertion to enforced error handling, with the commit message noting it “protects against a compromised renderer requesting a frame size change at an unexpected time.”

Key insight
The precondition that the input queue be empty before a resolution change was guarded only by a DCHECK, which is absent in release builds; the fix makes it a real runtime check that reports an error and returns.

Attack Path

  1. Queue frames at one size A renderer sends encode requests that populate pending_input_queue_ with frames at the current resolution. (inferred)
  2. Request a resolution change mid-stream Before those frames drain, it requests a frame-size change, entering UpdateFrameSize.
  3. Bypass the debug-only assertion In a release build the DCHECK(pending_input_queue_.empty()) at line 1106 is compiled out, so reconfiguration proceeds with stale frames still queued.
  4. Stale frame fed to resized MFT A queued frame sized for the old resolution is later processed by the MFT now configured for the new one, which the advisory ties to an out-of-bounds read. (inferred)

Impact Assessment

A compromised renderer could request an encoder resolution change while input frames were still queued, which in release builds bypassed the debug assertion and could feed mismatched-size frames to the reconfigured MFT, leading (per the advisory) to an out-of-bounds read and information disclosure in the GPU process. The advisory rates this medium severity and not exploited in the wild. The downstream OOB read occurs in vendor MFT/driver code outside this material, so that step is (inferred).

Files Changed

  • media/gpu/windows/media_foundation_video_encode_accelerator_win.cc

Audit Directions

  • DCHECK as a security boundary
    Flag any DCHECK/DCHECK_* guarding a precondition that untrusted input can violate; release builds omit it, so it must be a real runtime check.
  • Reconfiguration with pending work
    Audit encoder/decoder reconfiguration paths for leftover queued buffers sized to the previous configuration.
  • Size-mismatch to hardware
    Where buffers are handed to vendor/hardware APIs, verify their size matches the currently configured dimensions before submission.
From 65ff0534249fe614b4e40d7f155d801071a72eca Mon Sep 17 00:00:00 2001
From: Dale Curtis <[email protected]>
Date: Fri, 03 Apr 2026 13:01:23 -0700
Subject: [PATCH] [MFVEA] Promote DCHECK to error handling

This protects against a compromised renderer requesting a frame size
change at an unexpected time.

R=eugene

Fixed: 499052720
Change-Id: I621891344f7b94e5878af3e2c1873f2d936b927e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7728102
Auto-Submit: Dale Curtis <[email protected]>
Reviewed-by: Eugene Zemtsov <[email protected]>
Commit-Queue: Eugene Zemtsov <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1609923}
---

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 58983a5..48ad40b 100644
--- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
+++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
@@ -1103,7 +1103,15 @@
   DCHECK(activate_);
   DCHECK(encoder_);
   DCHECK_NE(input_visible_size_, frame_size);
-  DCHECK(pending_input_queue_.empty());
+
+  // This is not normally possible, but a compromised renderer could cause it
+  // to be reached.
+  if (!pending_input_queue_.empty()) {
+    NotifyErrorStatus({EncoderStatus::Codes::kEncoderIllegalState,
+                       "Can't change frame size when there are pending input "
+                       "frames"});
+    return;
+  }
 
   if (!IsFrameSizeAllowed(frame_size)) {
     NotifyErrorStatus({EncoderStatus::Codes::kEncoderUnsupportedConfig,
Loading diff…

Original Bug Report

reported by [email protected]

Potential GPU OOB read and info leak in MediaFoundationVideoEncodeAccelerator due to stale queue

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: MediaFoundationVideoEncodeAccelerator fails to clear its pending input queue when reconfiguring for a new resolution. A compromised renderer can exploit this to queue a small buffer, reconfigure the encoder to a large resolution, and cause the underlying MFT to perform an out-of-bounds read. The leaked GPU process memory is encoded into the bitstream and returned to the attacker.

Affected files:

  • media/gpu/windows/media_foundation_video_encode_accelerator_win.cc

Estimated timestamp from git blame: 2024-12-03

Vulnerability Details

The MediaFoundationVideoEncodeAccelerator (MFVEA) on Windows contains a flaw in how it handles dynamic resolution changes via UpdateFrameSize(). When a resolution change occurs, the accelerator reconfigures the underlying Media Foundation Transform (MFT) but fails to properly flush or clear its internal pending_input_queue_.

In media/gpu/windows/media_foundation_video_encode_accelerator_win.cc, UpdateFrameSize() uses a DCHECK to assert that the queue is empty before proceeding:

// media/gpu/windows/media_foundation_video_encode_accelerator_win.cc:1036
DCHECK(pending_input_queue_.empty());

Because DCHECK macros are compiled out in Release builds, execution proceeds even if the queue contains frames. The method updates the input_visible_size_ and reconfigures the MFT to the new dimensions. While it explicitly clears bitstream_buffer_queue_ (line 1143), it leaves pending_input_queue_ untouched.

Potential Exploitation Steps

Note: These steps are based on static analysis; a working Proof of Concept has not yet been executed.

  1. Queue a Small Frame: A compromised renderer process floods the GPU process with asynchronous Encode Mojo IPCs containing small VideoFrame objects (e.g., 16x16).
  2. Buffer Allocation: QueueInput() creates IMFSample buffers for these frames based on the current 16x16 input_visible_size_ and pushes them onto pending_input_queue_.
  3. Trigger Resolution Change: Before the hardware encoder finishes processing, the attacker sends a RequestEncodingParametersChange IPC with a large resolution (e.g., 1920x1080).
  4. Reconfiguration: The GPU process calls UpdateFrameSize(), bypassing the DCHECK. The MFT is reconfigured to expect 1080p frames, and input_visible_size_ becomes 1920x1080. The 16x16 samples remain in pending_input_queue_.
  5. Feeding Stale Inputs: When the MFT signals METransformNeedInput, FeedInputs() dequeues the stale 16x16 sample and passes it to encoder_->ProcessInput() without verifying the sample’s buffer size against the new input_visible_size_.
  6. Out-of-Bounds Read: The vendor MFT driver (Intel, NVIDIA, AMD) relies on its newly configured MF_MT_FRAME_SIZE (1080p). It assumes the provided buffer is large enough and reads past the end of the 16x16 allocation, resulting in an out-of-bounds read into adjacent GPU heap memory.
  7. Information Leak: The leaked heap memory is encoded as video data and returned to the renderer via the BitstreamBufferReady callback, allowing the attacker to bypass ASLR or steal cross-origin texture data.

Suggested Fix

There are two primary ways to fix this issue:

  1. Clear the Queue on Reconfiguration: In UpdateFrameSize(), explicitly clear the pending_input_queue_ and properly discard/notify the client about the dropped frames, similar to how bitstream_buffer_queue_ is cleared.
  2. Validate Sample Size Before Processing: Add a check in ProcessInput() or FeedInputs() to ensure that the IMFSample buffer dimensions match the currently configured input_visible_size_. If they do not match, the sample should be rejected rather than passed to the hardware encoder.

Evaluated with Chrome root at commit: ff3d2b74fa39431785bd60e51463b08fcc71ee33


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.

View on issue tracker