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