How HTTP Works

Response header

< Cross-Origin-Opener-Policy: same-origin

Cross-Origin-Opener-Policy

Learn how Cross-Origin-Opener-Policy (COOP) isolates your browsing context from cross-origin documents. Required for SharedArrayBuffer and enhanced security.

Reviewed 2 min readadvanced2 sourcesTry itMarkdown
Direction
Response
Category
Security
Spec
HTML Standard
On this page

TL;DR: Cross-Origin-Opener-Policy: same-origin separates your top-level document from incompatible popup/opener contexts. It can break OAuth and payment popup callbacks. Use it with COEP for cross-origin isolation; same-origin-allow-popups preserves only certain popup relationships.

What is Cross-Origin-Opener-Policy?

COOP determines whether top-level documents share a browsing context group. A group switch severs their window references. This is different from CORS, which controls sharing fetched responses, and from X-Frame-Options, which controls framing. Both documents’ origins and policies matter. HTML defines the matching rules.

Syntax

Cross-Origin-Opener-Policy: same-origin

Return it on the document response. It is not an API access-control header.

Value Guide

  • unsafe-none is the default. It does not request isolation, but another document’s policy can still force a group switch.
  • same-origin shares a group only with same-origin documents that have a matching policy.
  • same-origin-allow-popups matches same-origin documents with that same policy, and permits popups opened with window.open() to remain connected when the popup uses unsafe-none.
  • noopener-allow-popups severs the incoming opener relationship, including from same-origin openers, while allowing the document to open unsafe-none popups.

These are behavioral rules, not guarantees of a particular OS process layout. Consult MDN’s navigation and window.open tables for combinations.

Example

Illustrative document response header excerpt:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Verify in the document:

console.log(window.isSecureContext, window.crossOriginIsolated)

Implementation

Inside the nginx server or location serving HTML:

add_header Cross-Origin-Opener-Policy "same-origin" always;

Use nginx’s header directive and inspect the final response after proxies or middleware have run. Duplicate or overridden policy headers are harder to diagnose than a single policy owned by one layer.

For an existing Express app, register document middleware before the route serving HTML:

app.use('/isolated', (_req, res, next) => {
  res.set({
    'Cross-Origin-Opener-Policy': 'same-origin',
    'Cross-Origin-Embedder-Policy': 'require-corp'
  })
  next()
})
app.get('/isolated', (_req, res) => {
  res.sendFile('isolated.html', { root: '/srv/app/public' })
})

Create /srv/app/public/isolated.html for this route. Express supports header middleware and rooted file responses. Scope these headers to the documents that need isolation, then test their resources and popup flows.

Operational Impact

For a popup flow, inspect the document response after every navigation, including the identity-provider page and callback. A group switch can make window.opener null and make the opener’s retained window handle appear closed. MDN documents severed window.open references.

Calling window.opener.postMessage(...) when window.opener is null throws; it does not silently deliver or silently succeed. Log the opener value on the callback page before investigating message handlers.

COOP, COEP, and CORP Together

COOP controls window relationships. COEP controls resource embedding requirements. CORP is one resource-side way to satisfy no-cors embedding requirements. A global CORP header is not a third mandatory switch for isolation; successful CORS loads can satisfy the resource checks instead.

COOP and Cross-Origin Isolation

For a secure top-level document, use COOP same-origin with COEP require-corp or credentialless. The cross-origin-isolated permissions policy must also allow the capability. Check crossOriginIsolated before selecting a SharedArrayBuffer path.

same-origin-allow-popups does not provide that isolation capability. It can preserve an OAuth popup using unsafe-none, but cannot override a restrictive policy sent by the provider. Test the actual provider and callback rather than assuming that changing the opener header repairs every flow. Redirect-based login avoids depending on a surviving popup opener reference.

Frequently asked questions

What is Cross-Origin-Opener-Policy?

COOP controls whether top-level documents share a browsing context group. Matching depends on both documents policies and origins, and a group switch severs window references.

What values can COOP have?

The values are unsafe-none, same-origin, same-origin-allow-popups, and noopener-allow-popups. unsafe-none is the default; popup exceptions depend on the other document policy.

Why use COOP?

COOP limits opener relationships and helps mitigate cross-window attacks. COOP same-origin combined with an appropriate COEP policy can enable cross-origin isolation.

What is cross-origin isolation?

In a secure context, COOP same-origin plus COEP require-corp or credentialless can enable the capability, unless permissions policy blocks it. Verify window.crossOriginIsolated rather than headers alone.

Sources

  1. MDN Web Docs: Cross-Origin-Opener-Policydeveloper.mozilla.org
  2. HTML Standard: Cross-origin opener policieshtml.spec.whatwg.org

Keep going

Browse /search