# Cross-Origin-Opener-Policy header is set

- **Pattern:** `ab-002436` (`security-headers-ii.cross-origin-isolation.coop-set`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002436
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002436)

## Why it matters

Without `Cross-Origin-Opener-Policy`, a cross-origin page that your app opens (or that opens your app) can hold a reference to your `window` object. Spectre-class speculative-execution attacks use cross-origin window references and shared memory to read data across origin boundaries. CWE-1021 (Improper Restriction of Rendered UI Layers / Frame Hijacking) applies. OWASP A05 (Security Misconfiguration) flags missing isolation headers as a configuration gap. The absence of COOP also prevents the browser from enabling `SharedArrayBuffer` and high-resolution timers, which are required for performant web workers in security-sensitive contexts.

## Severity rationale

Medium because Spectre-class attacks require local code execution and specific browser conditions, but the window reference exposure is a prerequisite that is cheap to eliminate with a single header.

## Remediation

Set `Cross-Origin-Opener-Policy` in your Next.js headers config. Use `same-origin-allow-popups` if your app opens OAuth flows or payment windows; use `same-origin` for maximum isolation.

```js
// next.config.js
module.exports = {
  async headers() {
    return [{
      source: '/(.*)',
      headers: [{
        key: 'Cross-Origin-Opener-Policy',
        value: 'same-origin-allow-popups'
      }]
    }]
  }
}
```

Verify OAuth popups still function after deploying — `same-origin` will break popup-based OAuth flows that communicate via `window.opener`. Switch to `same-origin-allow-popups` if you hit that issue.

## Detection

- **ID:** `coop-set`
- **Severity:** `medium`
- **What to look for:** Check framework config, middleware, and deployment config for a `Cross-Origin-Opener-Policy` (COOP) header. Acceptable values: `same-origin` (strictest — isolates the window completely) or `same-origin-allow-popups` (allows OAuth popups, payment windows). COOP isolates the browsing context from cross-origin references, preventing Spectre-class side-channel data leaks.
- **Pass criteria:** COOP header is set to `same-origin` or `same-origin-allow-popups` — at least 1 location must configure it. Quote the actual header value and count all locations where COOP is configured (framework config, middleware, deployment config).
- **Fail criteria:** No COOP header configured, or COOP is set to `unsafe-none` (the default, provides no protection).
- **Do NOT pass when:** COOP is set to `unsafe-none` — this is the browser default and provides no protection.
- **Skip (N/A) when:** Project is an API-only service with no browser-facing pages.
- **Detail on fail:** `"No Cross-Origin-Opener-Policy header configured — window is not isolated from cross-origin references"` or `"COOP set to unsafe-none — provides no Spectre-class protection"`
- **Remediation:** COOP prevents cross-origin windows from accessing your window object, mitigating Spectre-class attacks:

  ```js
  // next.config.js
  headers: [{
    key: 'Cross-Origin-Opener-Policy',
    value: 'same-origin-allow-popups'
  }]
  ```

  Use `same-origin-allow-popups` if your app opens OAuth popups or payment windows. Use `same-origin` for maximum isolation if you don't need cross-origin popups.

## External references

- cwe CWE-1021
- owasp A05

Taxons: access-control

HTML version: https://auditbuffet.com/patterns/ab-002436
