Earning cross-origin isolation
Powerful web APIs such as SharedArrayBuffer and unthrottled
performance.now() are gated behind cross-origin isolation. A document earns
it by combining three headers — Cross-Origin-Opener-Policy (COOP),
Cross-Origin-Embedder-Policy (COEP) and, on its subresources,
Cross-Origin-Resource-Policy (CORP). This reference covers each header’s
values and computes whether a given COOP/COEP pair isolates the page.
How it works
COOP controls the document’s browsing-context group; COEP controls how it may embed cross-origin resources; CORP is set by each resource to declare who may embed it:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: cross-origin
Isolation is granted only when the top-level document sends
COOP: same-origin and COEP: require-corp or credentialless. With
require-corp, every cross-origin subresource must opt in with a CORP
header (or be loaded via CORS) or the browser blocks it. credentialless
relaxes that by loading no-CORS cross-origin resources without credentials.
Header values at a glance
Cross-Origin-Opener-Policy (COOP)
| Value | Effect |
|---|---|
same-origin | Page is in its own browsing-context group; enables isolation |
same-origin-allow-popups | Keeps opener reference for popups you open; does NOT isolate |
unsafe-none | Default; pages can share a group with cross-origin opener |
Cross-Origin-Embedder-Policy (COEP)
| Value | Effect |
|---|---|
require-corp | Blocks cross-origin resources that do not send CORP or CORS |
credentialless | Fetches no-CORS cross-origin resources without credentials |
unsafe-none | Default; no restrictions on embedding |
Cross-Origin-Resource-Policy (CORP)
| Value | Set by | Effect |
|---|---|---|
same-origin | Resource | Only the same origin may load this resource |
same-site | Resource | The same eTLD+1 may load it |
cross-origin | Resource | Any origin may load it under COEP require-corp |
What isolation actually unlocks
Once self.crossOriginIsolated is true, the following become available:
SharedArrayBuffer(used for multi-threaded WebAssembly, Atomics)- High-resolution
performance.now()(unthrottled timer) postMessagewithAtomics.wait()onSharedArrayBufferobjects
These APIs were restricted after the Spectre timing-attack class of vulnerability. Cross-origin isolation proves the page cannot read cross-origin memory, satisfying the security constraint.
Practical rollout order
- Audit every cross-origin resource your page loads (images, fonts, scripts, iframes).
- Add
Cross-Origin-Resource-Policy: cross-originto resources you control. - For third-party resources you cannot modify, choose
COEP: credentiallessinstead ofrequire-corp. - Set
COOP: same-originand verify no popup flows rely onwindow.opener. - Deploy both headers and confirm
self.crossOriginIsolated === truein the browser console.
Tips and notes
- Both COOP and COEP must be present and correct — one alone does nothing.
- Audit subresources before enabling COEP; missing CORP/CORS will break images, scripts and fonts.
COOP: same-origin-allow-popupskeeps opener for popups you open but does not enable isolation.- Check
self.crossOriginIsolatedat runtime to confirm the page is isolated. - Prefer
credentiallessfor faster rollout when you cannot add CORP to every dependency.