WebKit: UXSS: enqueuePageshowEvent and enqueuePopstateEvent don't enqueue, but dispatch CVE-2017-2510 Here is a snippet of CachedFrameBase::restore which is invoked when cached frames are restored. void CachedFrameBase::restore() { ... for (auto& childFrame : m_childFrames) { ASSERT(childFrame->view()->frame().page()); frame.tree().appendChild(childFrame->view()->frame()); childFrame->open(); <----- (a) } ... // FIXME: update Page Visibility state here. // https://bugs.webkit.org/show_bug.cgi?id=116770 m_document->enqueuePageshowEvent(PageshowEventPersisted); HistoryItem* historyItem = frame.loader().history().currentItem(); if (historyItem && historyItem->stateObject()) m_document->enqueuePopstateEvent(historyItem->stateObject()); frame.view()->didRestoreFromPageCache(); } enqueuePageshowEvent and enqueuePopstateEvent are named "enqueue*", but actually those *dispatch* window events that may fire JavaScript handlers synchronously. At (a), |open| method may invoke |CachedFrameBase::restore| method again. Thus, the parent frame's document may be replaced while |open| is called in the iteration, the next child frame is attached to the parent frame holding the replaced document. PoC:
This bug is subject to a 90 day disclosure deadline. After 90 days elapse or a patch has been made broadly available, the bug report will become visible to the public. Found by: lokihardt