VULNERABILITY DETAILS ``` void FrameLoader::detachChildren() { [...] SubframeLoadingDisabler subframeLoadingDisabler(m_frame.document()); // ***1*** Vector, 16> childrenToDetach; childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount()); for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling()) childrenToDetach.uncheckedAppend(*child); for (auto& child : childrenToDetach) child->loader().detachFromParent(); } ``` When a cached page is being restored, and the page that's being navigated away is not cacheable, there exists a time frame during which two documents are attached to the same frame. If an attacker finds a way to run JS during this time frame, she will be able to use one of the documents to execute JavaScript in the context of the other one. One possible call stack that might lead to JS execution is: ``` a child frame's unload handler ... ContainerNode::disconnectDescendantFrames() Document::prepareForDestruction() FrameLoader::clear() FrameLoader::open() ``` By the time `FrameLoader::clear` is called, child frames are usually already disconnected from the document via ``` FrameLoader::detachChildren() FrameLoader::setDocumentLoader() FrameLoader::transitionToCommitted() ``` However, the attacker can initiate a new page load inside `detachChildren` to bypass `SubframeLoadingDisabler` and create a new child frame. Note that it won't cancel the cached page load. The attack has a restriction that significantly limits its applicability -- a victim page should load a (potentially sandboxed)