What Is Cross-Origin Isolation? Complete Guide (2026)

Saar Twito8 min read
Saar Twito
Saar TwitoFounder & SEO Engineer

Hi, I'm Saar - a software engineer, SEO specialist, and lecturer who loves building tools and teaching tech.

View author profile →

What Is Cross-Origin Isolation?

Cross-origin isolation is a browser security state that locks your page into its own isolated process, preventing other origins from sharing memory or accessing timing data that could be exploited in Spectre-style side-channel attacks. A page enters the cross-origin isolated state when it sends two HTTP response headers together: Cross-Origin-Opener-Policy: same-origin (COOP) and Cross-Origin-Embedder-Policy: require-corp (COEP). The full mechanics are defined in the HTML Living Standard (Origin section) and explained in Google's web.dev cross-origin isolation guide.

The origin of this feature is the Spectre vulnerability, publicly disclosed on January 3, 2018 by Google's Project Zero and academic researchers. Spectre demonstrated that a malicious script running in the same process as another tab could use high-resolution timers to infer the contents of memory belonging to that tab — including passwords, session tokens, and private data. Browsers responded by disabling SharedArrayBuffer and reducing timer precision globally. Cross-origin isolation re-enables those powerful APIs safely, by guaranteeing that only same-origin content shares the same process.

Key Facts (TL;DR)

  • Two headers required: Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp.
  • What it enables: SharedArrayBuffer, performance.measureUserAgentSpecificMemory(), and high-resolution timers.
  • Why it exists: Protection against Spectre CPU side-channel attacks, disclosed January 2018.
  • Check in JS: self.crossOriginIsolated returns true when the state is active.
  • Sub-resource requirement: All cross-origin resources loaded by the page must opt in via a Cross-Origin-Resource-Policy header or CORS.
  • Greadme audit: Flagged under Security when COOP or COEP headers are missing or misconfigured.

The Spectre Attack — Why These Headers Exist

Spectre is a class of hardware vulnerability that affects most modern CPUs manufactured since the mid-1990s. It exploits speculative execution — a performance optimisation where the CPU runs instructions ahead of time and discards the results if they turn out to be unnecessary. An attacker can use carefully timed memory access patterns to infer what data the CPU was speculating on, even data it was not supposed to access.

In a browser, Spectre becomes dangerous when two different origins share the same OS process. A malicious script on evil.example in one tab could, in theory, use a SharedArrayBuffer as a high-resolution timer to read memory from yourbank.com open in another tab in the same process. All major browser vendors confirmed this class of attack as a realistic threat in 2018.

Browsers initially mitigated Spectre by disabling SharedArrayBuffer entirely and reducing timer precision across all pages. Cross-origin isolation is the long-term solution: by placing each cross-origin isolated page in its own dedicated process, the attack surface disappears — there is no shared memory to leak.

COOP: Cross-Origin-Opener-Policy

COOP controls the relationship between your page and any windows or tabs that open it or that it opens. By severing the browsing context group between cross-origin windows, COOP prevents other origins from accessing your page's window object — and from sharing its process.

ValueMeaningUse when
unsafe-noneDefault. No restriction — all windows share a browsing context groupLegacy behaviour; not recommended for security-sensitive pages
same-originOnly same-origin pages can share a browsing context group with your pageRequired for full cross-origin isolation (strictest)
same-origin-allow-popupsLike same-origin but retains access to popups your page opens to cross-origin URLsWhen your page needs to open third-party popups but does not need cross-origin isolation
restrict-propertiesSevers script access between cross-origin windows but preserves limited interactions like postMessage and closed. Enables cross-origin isolation when paired with COEP.Modern recommended path for sites that need OAuth/payment popups and cross-origin isolation (Chrome 116+)
noopener-allow-popupsSevers the opener relationship even for same-origin documents while still allowing popups to be openedWhen the opener should be fully isolated but your page must still open new windows
# Strictest — full isolation, no popup interaction
Cross-Origin-Opener-Policy: same-origin

# Modern path — isolation + safe OAuth/payment popups (Chrome 116+)
Cross-Origin-Opener-Policy: restrict-properties

# When you need popups but not full isolation
Cross-Origin-Opener-Policy: same-origin-allow-popups

See the MDN Cross-Origin-Opener-Policy reference and Chrome's restrict-properties announcement for current per-value browser support.

COEP: Cross-Origin-Embedder-Policy

COEP controls which cross-origin resources the page is allowed to load. It ensures that every cross-origin resource explicitly opts in to being loaded — preventing your page from inadvertently pulling in resources from origins that have not consented, which could otherwise be used to leak information.

ValueMeaningUse when
unsafe-noneDefault. Cross-origin resources load without any opt-in requirementLegacy behaviour; does not enable cross-origin isolation
require-corpAll cross-origin resources must send a Cross-Origin-Resource-Policy header or CORS headersRequired for cross-origin isolation (strictest)
credentiallessCross-origin no-CORS requests are sent without credentials; resources load without needing CORPEasier migration path when you cannot control third-party resource headers
# Strictest — all cross-origin resources must opt in
Cross-Origin-Embedder-Policy: require-corp

# More permissive — useful when third-party resources don't send CORP
Cross-Origin-Embedder-Policy: credentialless

CORP: Making Sub-Resources Compatible

When your page uses COEP: require-corp, every cross-origin resource it loads must respond with a Cross-Origin-Resource-Policy (CORP) header — otherwise the browser blocks it. This header is set on the server that serves the sub-resource (images, scripts, fonts, API responses), not on your page.

CORP valueWho can load this resource
same-originOnly the same origin
same-siteSame site (subdomains included)
cross-originAny origin — required for public CDN assets that any site can embed
# On a public CDN serving images or fonts to any site
Cross-Origin-Resource-Policy: cross-origin

# On an API that should only be called from the same site
Cross-Origin-Resource-Policy: same-site

If you cannot modify the headers on a third-party resource (e.g. a public CDN you do not control), use COEP: credentialless instead of require-corp — it lifts the CORP requirement for no-credentials requests while still enabling cross-origin isolation.

Enabling Cross-Origin Isolation: The Complete Header Set

To put your page into the cross-origin isolated state, send both COOP and COEP headers together on every response for that page:

# Full cross-origin isolation — strictest option
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

# Easier to deploy when you use third-party resources
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: credentialless

# Modern path — preserves OAuth/payment popups (Chrome 116+)
Cross-Origin-Opener-Policy: restrict-properties
Cross-Origin-Embedder-Policy: credentialless

After setting these headers, verify the state in the browser console:

// In the browser console — should return true
console.log(self.crossOriginIsolated); // true

If self.crossOriginIsolated returns false, one or both headers are missing, or a sub-resource is blocking the COEP requirement. Open Chrome DevTools → Application → Frames to see which resources are failing the COEP check.

What Cross-Origin Isolation Unlocks

Cross-origin isolation is not just a defensive measure — it is a prerequisite for several high-performance browser APIs that were disabled after Spectre:

  • SharedArrayBuffer — enables true shared memory between the main thread and web workers, required for high-performance WebAssembly applications, audio worklets, and multi-threaded games.
  • High-resolution timers (performance.now()) — full precision is restored under cross-origin isolation. Without it, browsers reduce timer precision (Chrome to roughly 100µs, Firefox historically to 1–2ms) to mitigate Spectre-style timing attacks.
  • performance.measureUserAgentSpecificMemory() — lets the page measure its own memory usage, useful for detecting memory leaks in long-running applications.
  • Atomics.wait on the main thread — required by some WebAssembly runtimes that expect POSIX-style blocking primitives.

See web.dev: Why you need cross-origin isolated for powerful features for the complete capability list.

Common Pitfalls When Enabling Cross-Origin Isolation

Third-party iframes break under COEP: require-corp

If your page embeds a third-party iframe (an ad, a video player, a map widget) and that third party does not send Cross-Origin-Resource-Policy: cross-origin, the iframe will be blocked. Either switch to COEP: credentialless, ask the third party to add the CORP header, or remove the embed.

OAuth popups break under COOP: same-origin

Many OAuth flows open a popup to a third-party identity provider and then communicate back to the opener via window.opener. With COOP: same-origin, the opener reference is severed — window.opener is null in the popup. The modern fix is COOP: restrict-properties (Chrome 116+), which preserves cross-origin isolation while still allowing safe interaction primitives like postMessage and closed. If you cannot rely on Chromium-only support yet, switch to COOP: same-origin-allow-popups (loses isolation) or migrate to redirect-based OAuth flows.

COEP blocks images and fonts from CDNs

Images and fonts loaded from a CDN without a Cross-Origin-Resource-Policy header will be blocked under require-corp. Ask the CDN provider to add Cross-Origin-Resource-Policy: cross-origin to its responses, or use COEP: credentialless which waives the CORP requirement for unauthenticated requests.

Applying headers to the wrong routes

COOP and COEP must be set on the HTML document response — not on sub-resources. Setting them only on an API endpoint has no effect. Apply them globally to all HTML responses, then handle any per-route exceptions for pages that embed third-party iframes.

How to Verify Cross-Origin Isolation

  • Browser console: self.crossOriginIsolated — returns true when the page is correctly isolated.
  • Chrome DevTools → Application → Frames — shows COOP and COEP status for the current frame and any sub-frames, and lists which resources are failing the COEP check.
  • Chrome DevTools → Network → response headers — verify that Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy appear on the HTML document response.
  • Greadme deep scan — audits COOP and COEP headers on your page and flags missing or misconfigured cross-origin isolation under Security.

FAQ

Do I need cross-origin isolation if I am not using SharedArrayBuffer?

Not strictly required, but still recommended for security-sensitive pages. Cross-origin isolation prevents other origins from sharing your page's process, reducing the attack surface for Spectre-style attacks even if you are not using shared memory APIs. For most sites, the bigger motivation is enabling SharedArrayBuffer for performance-intensive features.

Does cross-origin isolation break Google Analytics or Tag Manager?

It can. Scripts loaded via <script> tags are not affected by COEP, but iframes and certain cross-origin fetches may be blocked under require-corp. Using credentialless instead of require-corp reduces breakage significantly. Test in report-only mode if your tag manager loads iframes.

Is there a report-only mode for COOP and COEP?

Yes. Cross-Origin-Opener-Policy-Report-Only and Cross-Origin-Embedder-Policy-Report-Only send violation reports to a report-to endpoint without enforcing the policy. This lets you observe what would break before switching to the enforcing headers — the same pattern as Content-Security-Policy-Report-Only.

What is the difference between CORP and CORS?

CORS (Cross-Origin Resource Sharing) controls whether a browser allows a script on one origin to read the response from another origin — it is opt-in by the resource server and affects JavaScript-initiated fetches. CORP (Cross-Origin-Resource-Policy) controls whether the browser is allowed to load a resource at all into a cross-origin document — it is required by COEP and applies to all resource types including images and fonts, not just script-initiated fetches.

Does cross-origin isolation affect SEO or page performance?

Not directly. The headers are security controls — they do not affect how search engine crawlers index your content or how quickly the page loads. Indirectly, enabling SharedArrayBuffer and high-resolution timers can unlock performance improvements in compute-heavy applications (WebAssembly, audio processing), which may improve user experience metrics.

Can cross-origin isolation be enabled on a single page rather than the whole site?

Yes. COOP and COEP are per-response headers — you can enable cross-origin isolation only on the specific routes that need it (e.g. a WebAssembly-powered editor or a shared-memory audio worklet page) while leaving the rest of the site unaffected. Just ensure that every HTML response for those specific routes includes both headers.

Conclusion

Cross-origin isolation is the browser's answer to Spectre: two HTTP headers — Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp — that place your page in its own dedicated process, away from other origins. Beyond the security benefit, it unlocks SharedArrayBuffer and high-resolution timers for performance-intensive applications. The main adoption hurdle is ensuring that cross-origin sub-resources opt in via CORP headers; switching to credentialless mode reduces that friction significantly. Run a Greadme deep scan to check whether your COOP and COEP headers are present and correctly configured.