This Week in WebKit — June 06 - June 12, 2026
Featured
AddOriginAccessAllowListEntry and friends started life as a TestRunner SPI for letting layout tests bypass CORS, and they sat on NetworkConnectionToWebProcess with no [EnabledBy=...] annotation and no caller-side check that sourceOrigin belonged to the sender. A compromised WebContent could synthesize the IPC, inject any (sourceOrigin, destinationHost) tuple, and lift the same-origin policy — and because the allowlist lives process-globally inside the NetworkProcess, the lift applies transitively to every other WebContent sharing the network process. The fix gates all three messages behind AllowTestOnlyOriginAccessAllowListIPC, which is false in production.
When JSString::swapToAtomString swaps a string's underlying StringImpl for its atomized equivalent, the old String lands on Heap::m_possiblyAccessedStringsFromConcurrentThreads to keep the buffer alive while concurrent GC threads might still be reading it. Heap::finalize cleared that list at the end of every GC. Meanwhile a GCOwnedDataScope on the C++ stack holds a StringView into the old buffer — and a re-entrant JS callback (Symbol.toPrimitive, toString) invoked between buffer capture and consumption can trigger the swap and a full GC inside the same stack frame. The finalize then drops the only retention, freeing the bytes the stack still reads from.
Security fixes
-
NetworkProcess origin-allowlist IPC gating
High WebKit NetworkProcess
-
JSC heap UAF in swapToAtomString across GCOwnedDataScope
High JSC heap / string atomization
-
WebRTC DTLS UAF on RTCP-mux renegotiation
High libwebrtc DTLS transport
-
WebCore DOM UAF in Node::m_shadowIncludingRoot via destructor cascade
High WebCore DOM
Notable development
-
[GTK][WPE] Skia Compositor: use deferred display lists to paint tiles
refactor
-
[JSC] `Heap::clearConcurrentRetainedDataIfPossible()` should not run while concurrent marking is active
bug
-
[JSC] Move RegExp.prototype[Symbol.match] to C++
optimization
-
[JSC] Add DFG MultiGetByVal and MultiPutByVal
optimization
-
[Site Isolation] Implement Page.getResourceTree on the UIProcess ProxyingPageAgent
feature
-
[JSC] `isDefinitelyNonThenable` Structure cache can go stale when the prototype belongs to another realm
bug
-
[YARR] Add auto-possession optimization
optimization
-
Implement calc-mix()
feature
Other security-relevant changes
- [WebCore DOM Range] (Data race UAF)
ab48873— Added locking around mutations to Range boundary points (m_start, m_end) to prevent concurrent modification during garbage collection, which could cause use-after-free of container nodes. - [WebCore Streams] (type confusion)
96ec73a— Replaced jsCast with jsDynamicCast in ReadableStream cancel handler to prevent type confusion from fake Promise objects that could bypass runtime checks and corrupt memory. - [WebCore DOM] (UAF)
934ecdc— Fixed heap use-after-free in Node::shadowIncludingRoot caused by stale m_shadowIncludingRoot not being reset when nodes are detached. - [JSC DFG] (type confusion)
c7fe05e— Fixed DFG JIT constant folding of typeof/ToBoolean/CompareEq to respect realm-dependent semantics of MasqueradesAsUndefined objects, preventing type confusion in cross-realm checks. - [JSC BBQJIT] (aliasing)
a6f42da— Fixed BBQJIT tail call shuffle's failure to detect overlapping stack slots between 16-byte-aligned caller temps and packed callee arguments (e.g., v128 ranges), which could clobber source values before they are moved to their final locations. - [GPU Process AVF image decoder] (IPC boundary validation)
2f07319— Adds MESSAGE_CHECK at GPU process boundary to validate MIME type support before creating remote AVF image decoder, preventing WebProcess from sending unsupported types across IPC and triggering unvalidated decoder paths. - [WebCore FocusController] (UAF)
7aacc65— Fixed use-after-free in blur event dispatch when a focused element inside a shadow tree is removed and garbage collected during event handling. Without the fix, the browser would crash from accessing freed memory. - [JSC FTL OSR] (hole handling)
392f508— Fixed operationPopulateObjectInOSR to correctly skip unwritten array slots during FTL OSR exit materialization instead of passing them to putDirectIndex, preventing mishandling of uninitialized values. - [WebKit focus / gesture validation] (validator bypass)
f3a769a— Prevents popunder attacks by tracking user gesture consumption across window creation and focus operations; adds UserGestureTokenIdentifier to SetFocus and FocusRemoteFrame IPC to reject focus if gesture was already consumed. - [WebCore SharedWorkerScriptLoader] (CSP bypass)
d65bd81— Fixed CSP inheritance for SharedWorkers from blob:/data: URLs, which previously bypassed the creating document's CSP in importScripts() calls. - [WebCore CSP] (policy loss)
f8ed382— Fixed CSP policy loss where setHTTPHeaderField() was overwriting multiple CSP headers instead of appending them; blob: documents now correctly inherit all CSP policies from their creator, not just the last one. - [JSC DFG] (hardening)
0f5acb5— Fixed DFG incorrectly folding Promise.resolve to identity for Promise subclasses; now restricted to builtin Promise per spec. - [JSC wasm] (race condition)
24362e6— Fixed a data race in WebAssembly name section parsing where compiler threads and the main thread could simultaneously access the section without synchronization. Access now routed through a release/acquire accessor with lifetime safety preserved by retaining the initial name section reference. - [ANGLE validation] (OOB read)
08713e9— Fixed incorrect validation of large UNSIGNED_INT indexes in WebGL drawElements() by removing an erroneous explicit static cast that prevented proper range checking. The bug could have allowed out-of-bounds buffer access with attacker-controlled index values. - [WebCore Streams] (UAF)
42ec79c— Fixed use-after-free where m_controller could be freed on the main thread while the GC thread traversed it. Solution stores stream as JSValueInWrappedObject instead, properly managed across thread boundaries. - [WebCore AV1 decoder] (Undefined left-shift)
74eb129— Fixed undefined behavior in AV1 ULEB size decoding where left-shifting a uint8_t by >= 32 bits could corrupt parsed sizes; casting to size_t prevents the UB. - [WebCore graphics] (OOB write)
d343d17— Fixed inverted bounds check in removeClient() that caused out-of-bounds writes when accessing invalid indices and prevented removal of valid clients. - [WebCore CSP] (CSP bypass)
3ac584d— Fixed CSP 'self' bypass in sandboxed srcdoc iframes where inherited self-origin was reset to opaque origin during meta CSP tag processing, enabling cross-origin base URL injection. - [WebCore WebGL] (UAF)
6eff33b— Fixes use-after-free in EXTDisjointTimerQuery where query objects scheduled in event loop tasks could be garbage-collected before execution. Added proper ref-counting to ensure objects survive until the task completes. - [WebCore badging] (hardening)
3fa40e6— Enforces same-origin check for Navigator.setAppBadge/clearAppBadge, blocking cross-origin iframes from setting the app badge per W3C spec. Previously cross-origin scripts could succeed, violating origin isolation. - [WebKit Safe Browsing] (bypass)
0e4040c— Fixed safe browsing warning bypass during COOP process swaps where lookup results arriving before the response policy handler could skip the warning. Now shows warnings immediately from lookup completion. - [WebCore DOM] (race condition)
f88c5d9— Fixed race condition in Node::traverseToOpaqueRoot by storing opaque root directly in Node instead of computing during GC marking phase. Prevents concurrent-access condition that could occur during garbage collection. - [WebCore SpeechSynthesis] (null dereference)
ccfb13a— Added null checks in speech synthesis delegate callbacks to prevent null dereference crashes when m_synthesizerObject is freed while callbacks are pending. - [WebCore SourceBuffer] (crash)
1fd5d97— Fixed a crash in SourceBufferPrivate::removeCodedFramesInternal where invalid MediaTime comparisons return unordered values, bypassing guards and allowing invalid times as map keys. - [WebCore Streams] (lifetime fix)
64ad3f3— Prevented crash in StreamPipeToState::globalObject when an iframe is detached during stream.pipeTo() error handling; context->globalObject() returns null but was dereferenced without checking in jsDynamicCast.