← All issues

Site Isolation: UIProcess routing for same-site child frame back/forward navigations

212c74a

Source/WebKit/UIProcess/WebPageProxy.cpp

+ RefPtr<WebBackForwardListFrameItem> WebPageProxy::frameStateForBackForwardChildFrame(...)
+ {
+ auto* currentItem = m_backForwardList->currentItem();
+ ...
+ auto siblingIndex = frame.indexInFrameTreeSiblings();
+ return currentItem->findFrameStateInItem([&](auto& item) {
+ return item.childItemAtIndex(siblingIndex);
+ });
+ }

Source/WebKit/WebProcess/WebPage/WebFrame.cpp

void WebFrame::didReceivePolicyDecision(...)
{
+ if (policyDecision.backForwardFrameState) {
+ setHistoryItemForBackForwardNavigation(
+ HistoryItem::create(*policyDecision.backForwardFrameState));
+ }
...
+ if (navigationAction.policyAlreadyDecided())
+ frameLoader->loadRequestedHistoryItem(PolicyAlreadyDecided::Yes);
}

WebKit's Site Isolation model partitions web content into separate WebProcess instances per site, with the UIProcess acting as the trusted coordinator. Back/forward navigation is security-sensitive because it controls what URL a frame loads from history — a compromised WebProcess must not be able to resolve this unilaterally. The BackForwardList lives in the UIProcess; under the old path, the WebProcess performed its own child-item lookup via loadURLIntoChildFrame, which both bypassed UIProcess authority and didn't work correctly under Site Isolation.

This commit routes same-site child frame back/forward navigations through the UIProcess via the existing decidePolicyForNavigationAction IPC when UseUIProcessForBackForwardItemLoading is enabled. The UIProcess looks up the correct FrameState by sibling index in the BackForwardList, rewrites the request URL, and sends the FrameState back in the PolicyDecision.

Before (broken path):
  WebProcess: FrameLoader::loadURLIntoChildFrame
    └─► legacy loadChildHistoryItemIntoFrame
          └─► loads URL  [UIProcess not involved]

After (new path):
  WebProcess: loadURLIntoChildFrame
    └─► dispatchBackForwardItemLoading
          └─► decidePolicyForNavigationAction IPC ──► UIProcess
                                                       └─► frameStateForBackForwardChildFrame
                                                             └─► siblingIndex → BackForwardList lookup
                                                                   └─► PolicyDecision (FrameState attached)
                                                                         │
                                                                         ▼
                                                                   WebProcess: didReceivePolicyDecision
                                                                     └─► HistoryItem::create(FrameState)
                                                                           └─► loadRequestedHistoryItem

This closes a site isolation gap where child frame history navigations were bypassing UIProcess oversight, allowing the WebProcess to unilaterally resolve which historical URL a frame loads.

🔒

Frame-tree/BackForwardList sync assumptions and the new PolicyAlreadyDecided bypass create audit-worthy edge cases in this site isolation path.

Subscribe to read more