Medium CVSS 5.3 webkit UAF 🔧 Commit mapped

Overview

Medium
Severity
5.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionA malicious web extension may be able to cause an unexpected process crash
ComponentWebKit WebProcess
Bug ClassUAF
Tracker314642
Fix commit1759ab219c63 (WebKit/WebKit) +63/-3
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:N/A:H
CISA KEVNot listed
Crediteddr3dd
Disclosed2026-06-29

Background

WebExtension events
chrome/browser-style extension events (runtime.Port.onMessage/onDisconnect, devtools panel onShown) dispatch to registered JS listeners.
Iterator invalidation
Mutating a collection while iterating by reference invalidates iterators and can free elements still being visited.
Snapshot + RefPtr
Copying the list and holding a RefPtr per element makes dispatch resilient to add/remove during callbacks.

Root Cause Analysis

This fixes a use-after-free caused by mutating an event-listener list while iterating it during dispatch in the WebKit web-extension APIs. Three dispatch routines iterated their listener collections by reference and invoked each listener’s JS callback: WebExtensionContextProxy::dispatchDevToolsExtensionPanelShownEvent looped over extensionPanel->onShown().listeners(), and WebExtensionAPIPort::fireMessageEventIfNeeded / fireDisconnectEventIfNeeded looped over m_onMessage->listeners() / m_onDisconnect->listeners(), each calling listener->call(…). Calling into JS can run extension code that adds or removes listeners, mutating the very collection being iterated; the reference-based range-for then walks invalidated iterators / freed listener objects — a use-after-free.

The fix takes a copy of the listener list before iterating (auto listenersCopy = …listeners()) and iterates it as for (RefPtr listener : listenersCopy), so iteration proceeds over a stable snapshot and each listener is retained (RefPtr) across its call().

The restored invariant is that dispatch iterates an immutable snapshot and keeps every listener alive across the callback, regardless of listener mutations triggered by the callback. The regression test registers many onMessage/onDisconnect listeners, and inside a firing listener adds 1024 more, asserting the dispatch counts match the listeners present when the event fired (i.e. no crash and snapshot semantics).

Key insight
Extension event dispatch iterated the live listener list by reference while callbacks could add/remove listeners; copying the list and retaining each listener across call() removes the iterator-invalidation UAF.

Attack Path

  1. Register listeners A malicious/buggy web extension registers listeners on a runtime port (onMessage/onDisconnect) or a DevTools panel onShown event.
  2. Mutate during dispatch When the event fires, a listener callback adds or removes listeners, mutating the collection mid-iteration.
  3. Iterate freed entries The reference-based loop walks invalidated iterators / freed listener objects.
  4. Use-after-free Dispatch dereferences a freed listener in the WebContent (extension world) process.

Impact Assessment

A use-after-free in the WebContent process (extension content world), reachable by a malicious web extension that mutates its own listener set during event dispatch. It requires an installed/malicious extension, narrowing reach, but the UAF is attacker-controlled and can escalate beyond the advisory’s crash with grooming.

Changed Functions

FunctionChangeNotes
WebExtensionContextProxy::dispatchDevToolsExtensionPanelShownEvent
Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIDevToolsExtensionPanelCocoa.mm
modified Copies onShown().listeners() and iterates the snapshot as RefPtr listeners before calling each, so mutations during call() are safe.
WebExtensionAPIPort::fireMessageEventIfNeeded
Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIPortCocoa.mm
modified Iterates a copied m_onMessage listener list with RefPtr elements to avoid UAF when call() mutates the listeners.
WebExtensionAPIPort::fireDisconnectEventIfNeeded
Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIPortCocoa.mm
modified Same snapshot-and-retain fix for the onDisconnect listener dispatch.

Files Changed

  • Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIDevToolsExtensionPanelCocoa.mm
  • Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIPortCocoa.mm
  • Tools/TestWebKitAPI/Tests/WebKit/WKWebView/WKWebExtensionAPIRuntime.mm

Audit Directions

  • Other extension dispatch loops
    Grep the WebExtension API .mm files for for (… : …listeners()) followed by listener->call() without a prior copy; each is a candidate UAF.
  • Observer callbacks that reenter
    Audit event/observer dispatch across WebKit for iteration over live lists whose callbacks can mutate the list.

Original Bug Report

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