Cross-Origin-Opener-Policy: Isolate Your Browsing Context
When one page opens another with window.open() or a link with target="_blank", the two windows
can keep references to each other: the opened page sees window.opener, and the opener holds a
handle to the new window. Across origins, those handles are restricted, but not enough. A hostile
page that opens yours, or that you open, can still navigate your window, count its frames and
observe timing. Attacks known as cross-site leaks (XS-Leaks) use these signals to learn things about
a logged-in user, and some phishing tricks rely on swapping out the opener page.
Cross-Origin-Opener-Policy (COOP) tells the browser to put your page in its own browsing context group, so windows from other origins do not get a handle to it at all.
The values
| Value | Effect |
|---|---|
unsafe-none |
the default: no isolation |
same-origin-allow-popups |
other sites that open your page lose their handle; popups you open keep a link to you |
same-origin |
full isolation: only same-origin pages that also send same-origin share a context |
A newer value, noopener-allow-popups, exists in some browsers for special cases; most sites do
not need it.
Choosing a value with popups
same-origin is the strongest choice, but it also cuts the link to popups you open on other
origins. That matters for flows that open a third-party window and wait for it to report back
through window.opener:
- OAuth and social sign-in popups (“Sign in with Google” in a popup window);
- payment providers that open a 3-D Secure or wallet window;
- some document signing and file picker integrations.
With same-origin, those popups can no longer reach your page, and the flow hangs. Use
same-origin-allow-popups on pages that start such flows, or switch the integration to a redirect
flow, which works with full isolation. Pages that open no cross-origin popups can use
same-origin.
Roll out with the report-only variant first, which tells you what would break without enforcing
anything (reports need a report-to endpoint, configured with the Reporting-Endpoints header):
Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="coop"
How to set it
nginx:
add_header Cross-Origin-Opener-Policy "same-origin" always;
Apache:
Header always set Cross-Origin-Opener-Policy "same-origin"
Cloudflare: add the header with a Response Header Transform Rule (Rules → Transform Rules → Modify Response Header).
The header only has an effect on documents (HTML pages), so there is no harm in sending it on every response.
Cross-Origin-Resource-Policy (CORP)
We also show your Cross-Origin-Resource-Policy header, which is related but protects a different
thing. COOP is about windows; CORP says which sites may load a resource (an image, script or file)
at all:
same-origin: only your own origin;same-site: your origin and its sibling subdomains;cross-origin: anyone.
CORP helps against attacks that load your resources into another site’s process to read them. It
is also required, together with COOP same-origin and Cross-Origin-Embedder-Policy, for “cross-origin
isolation”, which unlocks features such as SharedArrayBuffer. CORP does not affect the result of
this check.
How PerfoMetrix checks this
We read the headers on the page response we already downloaded. We send no extra requests to your site.
The check passes when Cross-Origin-Opener-Policy is same-origin or same-origin-allow-popups,
and needs attention when the header is missing or has another value. The report also shows the CORP
value, if any. A report-only COOP header does not count as a pass, because it enforces nothing.
Further reading: MDN: Cross-Origin-Opener-Policy and web.dev: making your website cross-origin isolated.