← WebKit — 2026-W38

430a7b5b2f21c065bbf3487438516cc1e013af5f  AX: Fix use-after-free of accessibilityRootObjectWrapper

severity medium class UAF confidence 0.5 signal score 9.3 Source/WebKit/WebProcess
Primitive: unretained accessibility root wrapper returned from a secondary thread
Triage note: accessibilityRootObjectWrapper now holds the isolated-tree rootNode in a RefPtr and returns RetainPtr<id>{ root->wrapper() }.autorelease() instead of a bare root->wrapper(). Lifetime fix for the AX wrapper returned off the main run loop; a real memory-safety hardening but AX isolated tree is not directly web-attacker-reachable.
Structural signals: smartptr_member_added (+3.0), msg_strong (+3.0), msg_medium (+2.0), surgical (+1.3)

Commit message

AX: Fix use-after-free of accessibilityRootObjectWrapper
https://bugs.webkit.org/show_bug.cgi?id=316410
rdar://178730472

Reviewed by Chris Fleizach and Dominic Mazzoni.

The off-main-thread short-circuit in -[WKAccessibilityWebPageObjectBase
accessibilityRootObjectWrapper:] returned root->wrapper() as a raw +0
WebAccessibilityObjectWrapper*. The wrapper's only strong reference at that
moment was AXIsolatedObject::m_wrapper, kept alive transitively by the
local RefPtr<AXIsolatedTree>. Once the function returned, that RefPtr (and
the `root` it kept alive) went out of scope, freeing the wrapper before
the secondary AX thread's caller could retain it. AppKit subsequently
walked the autoreleased single-element NSArray returned by
-[WKAccessibilityWebPageObject accessibilityChildren] and called
objc_retain on the wrapper (and on the array) inside
-[__NSSingleObjectEnumerator initWithObject:collection:], crashing on
freed memory.

Wrap the returned wrapper in RetainPtr<id> { ... }.autorelease()
so it is retained synchronously while `tree`, `root`, and m_wrapper are
all still alive, and then deposited into the secondary thread's
autorelease pool. The pool keeps the wrapper alive for the rest of the
secondary thread's runloop iteration, long enough for AppKit's
ConvertOutgoingValueForElement -> objectEnumerator ->
initWithObject:collection: -> objc_retain sequence to finish safely.

* Source/WebKit/WebProcess/WebPage/mac/WKAccessibilityWebPageObjectBase.mm:
(-[WKAccessibilityWebPageObjectBase accessibilityRootObjectWrapper:]):

Originally-landed-as: [email protected] (cea3c1e1af92). rdar://184744967
Canonical link: https://commits.webkit.org/321080@main

Before / after

Loading diff…