Glossary
Cross-Origin-Opener-Policy
`Cross-Origin-Opener-Policy` controls whether a document keeps a scripting relationship with the window that opened it, or with windows it opens. Setting it to `same-origin` places the document in its own browsing context group, so a page from another origin holds no reference to it and cannot navigate it, probe its frame count, or use it as a side channel. It is also one of the two headers required to regain access to high-resolution timers.
What the window relationship allows
A page opened with `window.open` receives a reference to its opener, and the opener receives a reference to it. Both persist across navigation.
Even across origins, a limited set of operations remains available: navigating the other window, reading how many frames it has, closing it.
That is enough for a tab-napping attack, where a page opened from yours later navigates your tab to a convincing imitation while the visitor is elsewhere.
It is also enough to be a timing side channel, which is why the policy became a precondition for restoring precise timers after Spectre.
The values
`unsafe-none` is the default: the relationship is retained, which is how the web has always worked.
`same-origin-allow-popups` keeps references to windows this document opens, while severing the reference from an opener of another origin. This is the pragmatic middle setting.
`same-origin` severs both directions unless the other document is same-origin and also sets the policy. This is the strict setting and the one cross-origin isolation requires.
`rel="noopener"` on a link achieves the same severing for that one link, and has been the default for `target="_blank"` in browsers for several years.
A `report-to` variant of each value sends violation reports without enforcing, which is how a deployment is measured before it is switched on.
What it breaks
Popup-based authentication flows, where a login window communicates its result back to the opener. These require the opener reference.
Payment flows using the same pattern.
Anything using `window.postMessage` between a page and a popup of another origin.
`same-origin-allow-popups` exists precisely for these cases: it keeps what those flows need while removing the inbound risk.
Cross-origin isolation, and why it matters
Setting `Cross-Origin-Opener-Policy: same-origin` together with `Cross-Origin-Embedder-Policy: require-corp` puts the document in a cross-origin isolated state.
That state restores `SharedArrayBuffer` and high-resolution `performance.now`, both of which were restricted after the speculative execution vulnerabilities.
Applications that need them — video editors, emulators, anything compiled to WebAssembly with threads — have to adopt both headers, and therefore have to bring every embedded resource into compliance.
For an ordinary site that does not need those capabilities, `same-origin-allow-popups` alone is a sensible improvement with a much smaller cost.
Test before enforcing: `self.crossOriginIsolated` in the console reports whether the state was achieved, and the network panel names each resource that blocked it.
Frequently asked questions
- Will COOP break my login popup?
- same-origin will. same-origin-allow-popups keeps the reference to windows the page opens while severing an inbound opener from another origin.
- What is cross-origin isolation for?
- It restores SharedArrayBuffer and high-resolution timers, which were restricted after Spectre. It requires COOP same-origin and COEP require-corp together.
- Is rel=noopener enough?
- For links you control, it severs the opener reference. The header covers the whole document, including windows that opened it.
Sources
Related
VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.
Scan a website