Cross-Origin-Opener-Policy security response
Isolates your browsing context from cross-origin popups and windows — required to enable SharedArrayBuffer and high-resolution timers.
What it does
Cross-Origin-Opener-Policy (COOP) controls whether your page shares a browsing context group with cross-origin documents it opens (or that open it). When two pages share a browsing context group, they can access each other via window.opener — and share the same process, making Spectre-style memory attacks feasible.
By setting COOP: same-origin, your page gets its own isolated process. Cross-origin popups lose the window.opener reference to your page. This isolation is a prerequisite for re-enabling SharedArrayBuffer (which was disabled post-Spectre) and high-precision performance.now().
Syntax
Cross-Origin-Opener-Policy: unsafe-none
Cross-Origin-Opener-Policy: same-origin-allow-popups
Cross-Origin-Opener-Policy: same-origin
Values
unsafe-none (default)
No isolation. Your page shares a browsing context group with any cross-origin page that opens it or that it opens. Default browser behaviour. window.opener works across origins.
same-origin-allow-popups
Your page is isolated from cross-origin pages that open it. But popups your page opens that don't set their own COOP (or set unsafe-none) still share the group — window.opener still works from those popups to your page.
This is the practical middle ground for sites that need OAuth flows (which open popups for the OAuth provider and need window.opener to work for the redirect callback).
same-origin
Full isolation. Your page shares a browsing context group only with other same-origin pages that also set COOP: same-origin. All cross-origin pages — whether they opened your page or your page opened them — get a separate context group. window.opener returns null for cross-origin relationships.
Required (alongside COEP: require-corp) to enable SharedArrayBuffer and performance.now() with high resolution.
Enabling SharedArrayBuffer
Post-Spectre, browsers disabled SharedArrayBuffer globally. To re-enable it, your page needs to be in a "cross-origin isolated" context:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Both headers together create a cross-origin isolated context. self.crossOriginIsolated returns true. SharedArrayBuffer is available. performance.now() has full precision.
This matters for: WebAssembly multi-threading, advanced audio worklets, video processing, cryptographic applications, and any use case relying on shared memory between workers.
The OAuth popup problem
COOP: same-origin breaks the standard OAuth popup flow:
- Your page opens a popup to
oauth-provider.com/auth - User authenticates
- OAuth provider redirects popup back to
yoursite.com/callback - Callback page tries
window.opener.postMessage(token)→ fails (window.openeris null due to COOP)
Solutions:
- Use
COOP: same-origin-allow-popups— your page stays isolated from cross-origin openers, but popups you open can still usewindow.opener - Switch to redirect-based OAuth flow instead of popup
- Use
BroadcastChannelorlocalStorageevents instead ofwindow.opener
How it interacts with COEP and CORP
The three Cross-Origin-* headers form an isolation system:
- COOP (
same-origin) — isolates your browsing context from cross-origin windows - COEP (
require-corp) — requires all subresources to opt in to cross-origin loading - CORP (
cross-origin) — on resources, allows them to be loaded by COEP pages
Together COOP + COEP = crossOriginIsolated = true. CORP is needed on resources to not be blocked by COEP.
Common mistakes and gotchas
Setting COOP without COEP and expecting SharedArrayBuffer. Both are required. COOP alone doesn't enable cross-origin isolation.
Setting COOP: same-origin and breaking OAuth. Test your entire auth flow before deploying. If you use any popup-based OAuth, use same-origin-allow-popups or switch to redirects.
Not checking crossOriginIsolated in your app. If you need SharedArrayBuffer, check self.crossOriginIsolated at runtime and show a fallback or error if it's false — your COOP/COEP setup might not be complete everywhere (e.g., on older browsers).
Real-world examples
High-performance WebAssembly app needing SharedArrayBuffer:
HTTP/1.1 200 OK
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Site using OAuth popups — partial isolation:
HTTP/1.1 200 OK
Cross-Origin-Opener-Policy: same-origin-allow-popups
Standard site with no cross-origin isolation needs:
# Omit COOP, or:
Cross-Origin-Opener-Policy: unsafe-none
FAQ
Does COOP affect iframes?
COOP governs the relationship between top-level browsing contexts (windows and tabs), not iframes. Iframe isolation is handled by CSP sandbox, COEP, and CORP. COOP is about the window.opener relationship between popup windows and their openers.
What's self.crossOriginIsolated?
self.crossOriginIsolated is a JavaScript property that returns true when the page is in a cross-origin isolated context (COOP: same-origin + COEP: require-corp active). You can check it to conditionally use SharedArrayBuffer:
if (self.crossOriginIsolated) {
const sab = new SharedArrayBuffer(1024);
}
Does COOP affect SEO or page ranking?
No. COOP is a browser security policy with no effect on search engine indexing, ranking, or crawling. Search engine crawlers don't use window.opener or browsing context groups.
Fun fact
The window.opener property has been a security concern since the early days of JavaScript — in 2015, it was discovered that cross-origin pages could set window.opener.location to redirect your page to a phishing site (tabnapping). The fix was adding rel="noopener" to <a target="_blank"> links, which sets window.opener to null. COOP is the HTTP-header version of this protection, applying it systematically to all cross-origin context relationships rather than requiring developers to remember rel="noopener" on every external link.