[2] Cross-Process Page Identity Confusion in didPostMessage
Under Site Isolation, a compromised renderer could borrow any tab's identifier and have the UI process deliver scripted postMessage payloads to it.
Rated High because the diff exposes a UI-process IPC that resolves a global
WebPageProxyIdentifierand dispatches user-script messages into the target page without confirming sender ownership; a compromised renderer thereby injects payloads into another renderer'sWKScriptMessageHandler.
WebProcessProxy::didPostMessage() resolved a WebPageProxyIdentifier via the global WebPageProxy::fromIdentifier() and acted on the result without verifying that the page was hosted in the sending WebProcess. Under site isolation, the identifier is a process-agnostic handle; a compromised renderer could supply any page's identifier and have its forged postMessage payload delivered as if it had come from that page.
Source/WebKit/UIProcess/WebProcessProxy.cpp
Patch Details
A MESSAGE_CHECK_COMPLETION(isAssociatedWithPage(pageID), ...) is added immediately after the global lookup. isAssociatedWithPage is extended to consult m_remotePages (cross-origin iframe processes under site isolation) and a new m_pagesPendingClose counted set, populated by a new sendPageCloseMessage helper that wraps every Messages::WebPage::Close send. Call sites in ProvisionalPageProxy, RemotePageProxy, SuspendedPageProxy, and WebPageProxy are migrated to the helper.
Missing sender-authorization on a UI-process IPC handler that resolves a cross-process object handle via a global registry without checking it belongs to the sending process.
Background
WebPageProxy is the UI-process object representing a logical tab; under site isolation, multiple WebContent processes may attach to one page (a main-frame process plus per-site RemotePageProxy for cross-origin iframes). WebProcessProxy tracks which pages each renderer hosts via m_pageMap, m_provisionalPages, m_remotePages, and m_suspendedPages. WebPageProxyIdentifier is a globally unique handle resolved by WebPageProxy::fromIdentifier() regardless of asker. didPostMessage is the UI-process handler for window.webkit.messageHandlers.<name>.postMessage(...) from injected user scripts. MESSAGE_CHECK aborts the message and terminates the sending WebContent on failure.
Analysis
The handler accepted a renderer-supplied WebPageProxyIdentifier, resolved it globally, then dispatched the payload through the resolved page's WebUserContentControllerProxy with no ownership check. A compromised WebContent process could forge WebProcessProxy::DidPostMessage carrying a victim page's identifier and a serialized JS payload; the UI process would deliver it as if it originated from that page.
The fix also reveals a second-order problem: isAssociatedWithPage itself had to be extended to cover m_remotePages (so a process owning a page only via a cross-origin iframe is still recognized) and to introduce m_pagesPendingClose (a counted set that keeps isAssociatedWithPage true across the in-flight WebPage::Close round-trip, closing a TOCTOU window the helper did not previously cover).
Primitive: cross-process injection of attacker-controlled postMessage payloads into a victim page's WebUserContentControllerProxy. Application code routinely treats WKScriptMessageHandler callbacks as same-origin input from its own document — navigation triggers, credential operations, persisted state mutation are all reachable through this surface.
This vulnerability weakens the per-process boundary the UI process is supposed to enforce between WebContent processes — exactly the boundary the compromised-renderer threat model exists to defend.
Audit directions
- UI-process IPC handlers resolving cross-process handles via global registries. Audit every
WebProcessProxy::*IPC handler inWebProcessProxy.cppandWebProcessProxy.messages.inthat takes aWebPageProxyIdentifier,FrameIdentifier,WebUserContentControllerProxyidentifier, or similar. For each, confirm aMESSAGE_CHECK(isAssociatedWithPage(...))(or equivalent ownership check) exists before the resolved object is used. GrepSource/WebKit/UIProcess/*.cppforfromIdentifier(followed by use of the result without an interveningMESSAGE_CHECK. - Helper predicates falling out of date.
isAssociatedWithPagehad to be extended for bothm_remotePagesandm_pagesPendingClosehere. List everyWeakHashSet/HashMapmember ofWebProcessProxythat keys onWebPageProxyIdentifierand cross-check against the helper's body — service-worker pages, prewarmed pages, or PiP overlays would silently drop out. - TOCTOU between UIProcess-initiated teardown and renderer acknowledgement. The
m_pagesPendingCloseset exists to keepisAssociatedWithPagetrue across an in-flightWebPage::Close. Audit other UI-process teardown messages (WebFrameProxyremoval,WebUserContentControllerProxydetach, drawing-area destruction) for the same window — IPCs the renderer can legitimately send between UI-process state being cleared and the async reply arriving. WebPageProxyIdentifierreachability/predictability. These identifiers appear in IPC payloads a compromised renderer can observe and replay. Check whether allocation is predictable enough to enumerate unseen identifiers; start at the typedef andgenerate()implementation.