Medium CVSS 6.5 webkit UAF 🔧 Commit mapped

Overview

Medium
Severity
6.5
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionProcessing maliciously crafted web content may lead to an unexpected process crash
ComponentWebCore Platform/Graphics
Bug ClassUAF
Tracker313693
Fix commit5b76ce853191 (WebKit/WebKit) +21/-1
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
CISA KEVNot listed
CreditedJonathan Alush-Aben
Disclosed2026-06-29

Background

callOnMainThreadAndWait
A WTF helper that dispatches a task to the main thread and blocks the calling thread until it finishes, used when a non-main thread needs a main-thread-only API.
crossThreadCopy / isolatedCopy
WTF facilities that produce a deep, self-owned copy of a value (including its reference-counted String/Vector buffers) so it can be safely handed to another thread without sharing state.
MediaEngineSupportParameters
A WebCore struct bundling the content type, URL, and allowed container/codec/caption type lists used to ask a media engine whether it can play a given type.
Non-thread-safe String/Vector
WTF::String and Vector use reference counting and shared backing stores that are cheap to copy on one thread but unsafe to share or mutate concurrently across threads.
Lambda capture by reference ([&])
Captures surrounding locals by reference so the closure accesses the originals; across a thread boundary this shares the very objects the other thread must not touch.

Root Cause Analysis

MediaSource::isTypeSupported runs on a worker/script thread but must query MediaPlayer::supportsType, which has to execute on the main thread. To do so it used callOnMainThreadAndWait with a lambda that captured the local MediaEngineSupportParameters by reference ([&]) and then called MediaPlayer::supportsType(parameters) on the main thread. MediaEngineSupportParameters is a struct containing String and Vector<String>/Vector<FourCC> members (type, url, contentTypesRequiringHardwareSupport, allowedMediaContainerTypes/CodecTypes, etc.). These WTF String/Vector types are reference-counted/heap-backed but are NOT thread-safe to share across threads by reference: passing them by reference means the main thread touches the same underlying buffers that the originating thread owns, violating the invariant that cross-thread work must operate on data that has been deep-copied (crossThreadCopy / isolatedCopy) into thread-owned storage. Although callOnMainThreadAndWait blocks the caller until the main-thread task completes, capturing by reference still lets the two threads concurrently reference the same non-thread-safe String/Vector internals during the hand-off, and any implicit ref/deref, copy, or internal mutation of those shared buffers from the main thread races with the worker thread’s ownership, leading to use-after-free / heap corruption of the string buffers.

The fix changes the capture to [&supported, parameters = crossThreadCopy(WTF::move(parameters))], deep-copying the parameters into a thread-safe isolated copy that the main-thread lambda solely owns, so no non-thread-safe buffer is shared across the boundary. To support that, a new MediaEngineSupportParameters::isolatedCopy() && rvalue-qualified method is added in MediaPlayer.cpp/.h that crossThreadCopy()s each string/vector member and moves the trivially-copyable/plain members, giving crossThreadCopy a correct per-field deep-copy for this struct.

The restored invariant is: values handed to another thread must be isolated copies with no shared reference-counted state.

Key insight
A cross-thread hand-off captured non-thread-safe WTF String/Vector members by reference instead of deep-copying them; even though the caller waits, sharing reference-counted buffers across threads is a use-after-free waiting to happen, and the fix is to pass an isolatedCopy/crossThreadCopy instead.

Attack Path

  1. Run isTypeSupported off the main thread From maliciously crafted web content, invoke MediaSource.isTypeSupported(…) (or a code path reaching MediaSource::isTypeSupported) from a Worker or other non-main script thread so the callOnMainThreadAndWait hand-off is exercised.
  2. Supply complex type parameters Pass a content type / codec string that populates the String and Vector members of MediaEngineSupportParameters (type, allowed container/codec type lists), maximizing the reference-counted buffers shared by reference across the thread boundary.
  3. Race the shared buffers Cause the worker thread and the main thread to touch the same non-thread-safe String/Vector internals during the hand-off, so ref/deref or buffer access on one thread races the other’s ownership (inference: precise timing/interleaving needed to win the race is not shown by the diff).
  4. Trigger use-after-free The race frees or corrupts a String/Vector backing buffer while the other thread still references it, producing a use-after-free within WebCore’s media pipeline.
  5. Crash the process Per the advisory this yields an unexpected process crash; escalation beyond a crash would require additional heap-grooming and a separate corruption primitive not established by this commit.

Impact Assessment

The primitive is a use-after-free / cross-thread data race on reference-counted String/Vector buffers in the WebCore media pipeline, which the advisory characterizes as an unexpected process crash. Realistic escalation to a controlled corruption primitive would require reliably winning the hand-off race and grooming the freed buffer, which the diff does not establish; the most reliable outcome is a crash. It is confined to the process hosting the media/MediaSource logic (WebContent, or the GPU process where media decoding is offloaded) and remains within that sandbox.

Changed Functions

FunctionChangeNotes
MediaSource::isTypeSupported
Source/WebCore/Modules/mediasource/MediaSource.cpp
modified Changed the callOnMainThreadAndWait lambda from capturing parameters by reference ([&]) to capturing a deep isolated copy ([&supported, parameters = crossThreadCopy(WTF::move(parameters))]) so the main thread no longer shares the caller's non-thread-safe String/Vector buffers.
MediaEngineSupportParameters::isolatedCopy() &&
Source/WebCore/platform/graphics/MediaPlayer.cpp
added New rvalue-qualified method that crossThreadCopy()s each String/Vector member (type, url, contentTypesRequiringHardwareSupport, allowed container/codec type lists) and moves the plain members, providing a correct cross-thread deep copy of the struct.
MediaEngineSupportParameters (struct declaration)
Source/WebCore/platform/graphics/MediaPlayer.h
modified Declared WARN_UNUSED_RETURN WEBCORE_EXPORT MediaEngineSupportParameters isolatedCopy() && so crossThreadCopy can produce a thread-owned copy of the parameters.

Files Changed

  • Source/WebCore/Modules/mediasource/MediaSource.cpp
  • Source/WebCore/platform/graphics/MediaPlayer.cpp
  • Source/WebCore/platform/graphics/MediaPlayer.h

Audit Directions

  • Other by-reference captures into callOnMainThread*
    Grep WebCore for callOnMainThreadAndWait and callOnMainThread lambdas that capture [&] or [&, …] and inspect whether any captured local holds String/Vector/RefPtr state shared across the boundary rather than a crossThreadCopy.
  • Structs handed cross-thread without isolatedCopy
    Search for crossThreadCopy(…) usages and, conversely, structs with String/Vector members passed into cross-thread dispatch (dispatchToMainThread, Function, CrossThreadTask) that lack an isolatedCopy()&& overload; a missing isolatedCopy is the tell.
  • Media parameter plumbing across threads
    Audit MediaSource, SourceBuffer, and MediaPlayer paths that bridge worker/script threads to the main thread with MediaEngineSupportParameters or similar content-type structs, verifying each hand-off deep-copies rather than referencing caller-owned buffers.

Original Bug Report

The reporter's bug is still restricted on the tracker.