How COOP and COEP Prevent Side-Channel Attacks

Cross-Origin Opener Policy (COOP) and Cross-Origin Embedder Policy (COEP) are HTTP response headers that work together to place a web page into a “cross-origin isolated” state. This article explains how these mechanisms safeguard JavaScript memory by segregating browser processes and preventing side-channel timing attacks, such as Spectre, while allowing the safe use of powerful APIs like SharedArrayBuffer and high-resolution timers.

The Threat: Side-Channel Timing Attacks

Side-channel timing attacks exploit microscopic variations in CPU execution times to read unauthorized data from memory. In web browsers, vulnerabilities like Spectre demonstrated that malicious JavaScript could measure memory access latency via CPU cache states to infer sensitive data belonging to other origins sharing the same rendering process.

To execute these attacks effectively, an attacker requires two conditions: 1. Access to sensitive cross-origin data loaded into the same process memory space. 2. High-precision timing capabilities (such as SharedArrayBuffer or unthrottled performance.now()) to measure microarchitectural cache hits and misses.

Browsers initially mitigated this by reducing timer precision and disabling SharedArrayBuffer. COOP and COEP provide a structured mechanism to restore these capabilities securely by strictly isolating process memory.

Cross-Origin Opener Policy (COOP)

The Cross-Origin-Opener-Policy header isolates top-level documents from other windows. When a document specifies Cross-Origin-Opener-Policy: same-origin, the browser isolates the page in its own browsing context group.

This configuration prevents other websites that open your page—or pages opened by your page—from interacting with its window object or sharing execution processes. By severing the window.opener reference across different origins, COOP ensures that unauthorized external pages cannot access your page’s memory space via script interactions.

Cross-Origin Embedder Policy (COEP)

While COOP secures top-level browsing contexts, documents often load external subresources like images, scripts, stylesheets, and iframes. The Cross-Origin-Embedder-Policy header restricts how these resources are loaded into the page’s memory.

Setting Cross-Origin-Embedder-Policy: require-corp forces the browser to block any cross-origin resource that does not explicitly grant permission to be embedded. The resource must provide either a Cross-Origin-Resource-Policy (CORP) header or valid Cross-Origin Resource Sharing (CORS) headers. This stops unvetted, sensitive cross-origin data from ever being loaded into the document’s process memory.

Establishing Cross-Origin Isolation

When a server deploys both headers simultaneously:

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

The browser grants the page cross-origin isolated status (self.crossOriginIsolated === true).

In this state: * Process Boundary Enforcement: The operating system and browser ensure the document executes in an isolated process containing exclusively same-origin data and explicitly opted-in resources. * Leak Prevention: Because no unvetted cross-origin data resides in the process memory, there is no cross-origin data available for a side-channel attack to read. * API Restoration: Browsers can safely unlock high-resolution timers and features like SharedArrayBuffer and WebAssembly.Memory, as the timing mechanisms cannot be used to leak data across origins.