Medium chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in Codecs
DescriptionUninitialized Use in Codecs
ComponentCodecs
Bug ClassUninitialized Memory
Tracker504650654
Fix commit572f663c8934 (webm/libvpx) +1/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-07-29

Files Changed

  • vp8/vp8_dx_iface.c
From 572f663c893499db9e7f69bb2fec821eae6b1c40 Mon Sep 17 00:00:00 2001
From: Marco Paniconi <marpan@google.com>
Date: Tue, 16 Jun 2026 10:43:36 -0700
Subject: [PATCH] vp8: clear decoded_key_frame for resolution change

For resolution change: set decoded_key_frame to
0 to force successful keyframe at the new resolution,
before any inter frame is accepted.

Bug: 504650654
Change-Id: I89c3fedfb6babfbd24c25da1177e1cfade35de88
---

diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
index 7baf5c9..e6f9a36 100644
--- a/vp8/vp8_dx_iface.c
+++ b/vp8/vp8_dx_iface.c
@@ -430,6 +430,7 @@
         }
 #endif
 
+        pbi->decoded_key_frame = 0;
         if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height)) {
           vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                              "Failed to allocate frame buffers");
Loading diff…

Original Bug Report

reported by vm...@google.com

Renderer Heap Info Leak in VP8 via resolution-change longjmp and RTCRtpScriptTransform

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 potential vulnerability in libvpx’s VP8 decoder allows uninitialized heap memory to be leaked when a resolution change triggers buffer reallocation followed by a truncated frame error. This leaves reference buffers uninitialized but marked as valid. An attacker can use RTCRtpScriptTransform to bypass WebRTC error recovery and leak raw PartitionAlloc heap data to JavaScript.

Affected files:

  • third_party/libvpx/source/libvpx/vp8/vp8_dx_iface.c
  • third_party/libvpx/source/libvpx/vp8/common/alloccommon.c
  • third_party/libvpx/source/libvpx/vp8/decoder/decodeframe.c
  • third_party/libvpx/source/libvpx/vpx_scale/generic/yv12config.c
  • third_party/webrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc
  • third_party/webrtc/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate.cc

Estimated timestamp from git blame: 2021-10-08

Summary

A use-of-uninitialized-memory vulnerability in the VP8 decoder (libvpx) potentially allows an attacker to leak renderer-process heap memory to JavaScript. The issue occurs when a resolution change causes the reallocation of frame buffers, which is then interrupted by a longjmp error caused by a truncated partition. Due to incomplete error handling, reference buffers (GOLDEN and ALTREF) remain uninitialized but are not marked as corrupted. Subsequent frames can then use these buffers as prediction sources, copying raw heap data into output frames observable by the web page. This vulnerability is reachable without user interaction using WebRTC and the RTCRtpScriptTransform API.

Technical Details

1. Uninitialized Buffer Allocation in libvpx

In third_party/libvpx/source/libvpx/vpx_scale/generic/yv12config.c, vp8_yv12_realloc_frame_buffer allocates frame buffers using vpx_memalign (which uses PartitionAlloc). These buffers are only zeroed when compiled with MemorySanitizer (MSan):

if (!ybf->buffer_alloc) {
  ybf->buffer_alloc = (uint8_t *)vpx_memalign(32, frame_size);
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
  memset(ybf->buffer_alloc, 0, frame_size);
#endif
#endif
}
ybf->corrupted = 0;

In production builds, buffer_alloc contains uninitialized heap memory.

2. Resolution Change and Incomplete Error Handling

When a VP8 keyframe with a new resolution is processed, vp8_decode calls vp8_alloc_frame_buffers (in common/alloccommon.c), which reallocates all reference slots and resets the index map (lst=1, gld=2, alt=3). All buffers are freshly allocated and marked as non-corrupted (.corrupted=0).

If the subsequent decoding process (e.g., encountering a truncated partition) triggers a vpx_internal_error and longjmps back to the handler in vp8_dx_iface.c, only the last reference buffer (lst_fb_idx) is marked as corrupted:

if (setjmp(pbi->common.error.jmp)) {
  vpx_clear_system_state();
  /* We do not know if the missing frame(s) was supposed to update
   * any of the reference buffers, but we act conservative and
   * mark only the last buffer as corrupted. */
  pc->yv12_fb[pc->lst_fb_idx].corrupted = 1;
  /* ... */
}

The GOLDEN (gld_fb_idx=2) and ALTREF (alt_fb_idx=3) buffers remain uninitialized and marked as non-corrupted.

3. Persistence of Decoder State

The pbi->decoded_key_frame flag is not reset to 0 by the error handler in vp8_dx_iface.c. If a successful keyframe was decoded earlier in the session, the decoder allows subsequent inter frames even if the resolution-change keyframe failed. Additionally, LibvpxVp8Decoder::Decode does not set key_frame_required_ = true; after a vpx_codec_decode failure.

4. Exploitation via WebRTC and RTCRtpScriptTransform

Normally, WebRTC requires a new keyframe after a decode error. However, the RTCRtpScriptTransform API allows an attacker to bypass this. A transform worker can intercept an incoming frame marked as a keyframe at the transport layer, and replace its payload with a crafted VP8 inter-frame referencing the GOLDEN_FRAME. Because the metadata (is_keyframe) is preserved, WebRTC’s VideoStreamBufferController and LibvpxVp8Decoder::Decode keyframe checks are bypassed.

The VP8 decoder accepts the inter-frame, reads from the uninitialized GOLDEN_FRAME buffer (whose .corrupted flag is still 0), and copies raw heap content into the output frame, which can be read by JavaScript.

Impact

This is a renderer-process info leak. An attacker can potentially recover byte-exact contents of recently-freed PartitionAlloc allocations. This can be used to leak pointers (e.g., vtable pointers) and other sensitive data, serving as an ASLR-defeat or heap-grooming oracle for use in a multi-stage exploit chain.

Suggested Reproduction Steps

Note: These are potential steps as our tooling cannot currently run live exploits.

  1. Establish a loopback RTCPeerConnection and install an RTCRtpScriptTransform on the receiver.
  2. Send a valid VP8 keyframe to initialize the decoder and set decoded_key_frame = 1.
  3. Send a crafted keyframe with a new resolution and a truncated partition. This triggers buffer reallocation followed by a longjmp error.
  4. Send a third frame. Use the transform worker to replace the payload with a VP8 inter frame referencing the GOLDEN_FRAME (with ZEROMV). Ensure the transport-level metadata remains marked as a keyframe to bypass WebRTC pipeline checks.
  5. Read the resulting frame data in JavaScript (e.g., via MediaStreamTrackProcessor and an offscreen canvas). The pixel data should contain raw uninitialized heap memory.

Suggested Fix

In third_party/libvpx/source/libvpx/vp8/vp8_dx_iface.c, the error handler should be updated to conservatively mark all newly allocated reference buffers as corrupted when a decoding error occurs, especially immediately following a resolution change. Alternatively, vp8_yv12_realloc_frame_buffer should always zero-initialize the allocated memory, not just in MSan builds, to prevent uninitialized memory reads entirely.

Evaluated with Chrome root at commit: 7353d249d9cacf9c7218e1d7b8a39cf39c72d646


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