This Week in WebKit — June 20 - June 26, 2026
Featured
A REGRESSION crash traced a use-after-free: Node::cloneNode passed the document by bare reference, and LazyLoadVideoObserver::observe bound a long-lived reference into the Document-owned observer under a protect() temporary that died at the semicolon. Once that Ref dropped, a detached, GC-eligible document could be torn down — freeing the embedded observer before the very next line dereferenced it. The trigger is clean and deterministic: parse a detached document, drop all JS handles, GCController.collect(), then cloneNode(false) the video; the immediate primitive is a controlled crash, with escalation gated on reclaiming the freed slot under heap grooming. The fix pins the document with protect(document()) across the clone and adds LIFETIME_BOUND so the analyzer would have caught the escaping reference.
Site Isolation puts cross-site iframes in separate processes, but their FrameIdentifiers are globally addressable — and WebPasteboardProxy, the trusted UI-process broker, did no subtree check on the IDs it was handed. A compromised WebContent process serializing a copy of its own frame could name a completely unrelated cross-site frame as a "remote subframe," and the broker would reach into that frame's process, collect its serialized DOM, and write it to the pasteboard for attacker script to read back — a cross-site disclosure, not a sandbox escape, gated on already controlling a WebContent process and knowing the target ID. The fix walks every supplied identifier's parentFrame() chain and rejects any that doesn't descend from the root frame being copied. Note the deliberate soft spot: an unresolvable, already-detached frame is treated as allowed rather than rejected.
Threaded animations on macOS run a copy of the effect on the scrolling thread, so the same TimingFunction is reachable from both the main thread's keyframe interpolation and the scrolling thread's scroll path — each taking a transient ref before calling transformProgress. But TimingFunction still derived from plain RefCounted, whose ref()/deref() are non-atomic: two concurrent derefs can read the same count, and the inverse interleaving loses an increment so the object frees while a logical reference is live. It isn't a precise-timing exploit — looping enough concurrent animations while resolving the stack repeatedly is what eventually wins the race, which ASan surfaced on an existing threaded-animations test; the immediate outcome is a crash, not a confirmed corruption primitive. The one-line fix promotes the leaf to ThreadSafeRefCounted, matching the AcceleratedEffect graph that already used it.
NetworkBroadcastChannelRegistry validated the ClientOrigin on its IPC handlers but used the channel name directly as a HashMap key without checking it for null. The twist is where it faults: a null String has a null impl(), and StringHash::hash() dereferences it to compute the key's hash — which runs before HashTable::validateKey() would have rejected it, so the container's own safety net never fires. A compromised WebProcess forging a RegisterChannel/PostMessage with a valid origin and a null name reliably crashes the shared NetworkProcess, taking down networking for every browsing context — but there's no attacker-controlled data at the faulting address, so this is availability only. The fix adds MESSAGE_CHECK(!name.isNull()) at all three endpoints.
Security fixes
-
WebContent-supplied origin forwarded as authorization key at four UI-process IPC sites
Medium WebKit UIProcess permission and authorization plumbing
Notable development
-
[LBSE] Preserve paint order of non-composited children around composited SVG siblings
bug
-
Don't register WebM / MSE-AVF media players for GPU-process playback under MediaContainment
hardening
-
[JSC] Inline `NumericStrings` int cache lookup in DFG and FTL `ToString(Int32)`
optimization
-
[JSC] Replace fixup-inserted RegExp primordial `TryGetById` chains with a single `CheckStructure`
optimization
-
[WebXR Layers] Implement Cube layer
feature
-
[JSC] Implement `%RegExpStringIteratorPrototype%.next` in C++
optimization
-
[AppKit Gestures] Selection-drag autoscroll to the window edge on macOS
feature