← WebKit — 2026-W36

b7324636a8621b0623e36f72c08544177043c457  [CoreIPC][GPUP] UserMediaCaptureManagerProxySourceProxy can leave a dangling VideoFrameObserver* in RealtimeMediaSource

severity medium class UAF confidence 0.4 signal score 7.3 Source/WebKit/GPUProcess
Primitive: video frame observer re-added on constraint change even when the source proxy was not observing media
Triage note: UserMediaCaptureManagerProxySourceProxy now guards the remove/add video-frame-observer dance with m_isObservingMedia for Screen/Window capture. Without it, addVideoFrameObserver could register an observer that should not be active, risking a dangling-observer callback in the GPU process; plausible but not a concretely demonstrated UAF.
Structural signals: msg_strong (+3.0), msg_medium (+2.0), msg_soft (+1.0), surgical (+1.3)

Commit message

[CoreIPC][GPUP] UserMediaCaptureManagerProxySourceProxy can leave a dangling VideoFrameObserver* in RealtimeMediaSource
rdar://174702504

Reviewed by Jer Noble.

UserMediaCaptureManagerProxySourceProxy::sourceConfigurationChanged() re-registers
the proxy as a VideoFrameObserver of its RealtimeMediaSource via
removeVideoFrameObserver()/addVideoFrameObserver() without consulting m_isObservingMedia.
Since the proxy is registered as a RealtimeMediaSourceObserver unconditionally in its
constructor, this callback can fire on a stopped (or never-started) proxy and insert a
raw VideoFrameObserver* into m_videoFrameObservers while m_isObservingMedia remains
false. The destructor's unobserveMedia() then early-returns without removing the entry.

DisplayCaptureSourceCocoa does not override clone(), so UserMediaCaptureManagerProxy::clone()
yields two proxies sharing the same RealtimeMediaSource; the surviving clone keeps the
source (and its dangling raw key) alive after the first proxy is freed, and the next
videoFrameAvailable() virtual-dispatches through freed memory in the GPU process. This
is reachable from a compromised WebContent process over UserMediaCaptureManagerProxy IPC
once the page has been granted getDisplayMedia.

Guard the observer re-registration in sourceConfigurationChanged() on m_isObservingMedia
so a stopped proxy is never re-inserted into m_videoFrameObservers.

* LayoutTests/ipc/display-capture-source-configuration-change-uaf-expected.txt: Added.
* LayoutTests/ipc/display-capture-source-configuration-change-uaf.html: Added.
* Source/WebKit/GPUProcess/webrtc/UserMediaCaptureManagerProxy.cpp:
(WebKit::UserMediaCaptureManagerProxySourceProxy::sourceConfigurationChanged):

Originally-landed-as: 305413.1075@safari-7624.5-branch (a06fd51c1706). rdar://185367909
Canonical link: https://commits.webkit.org/320368@main

Before / after

Loading diff…