docs.rodeo

MDN Web Docs mirror

Cross-Origin-Opener-Policy

{{HTTPSidebar}} 

The HTTP Cross-Origin-Opener-Policy (COOP) {{glossary("response header")}}  allows a website to control whether a new top-level document, opened using {{domxref("Window.open()")}}  or by navigating to a new page, is opened in the same {{glossary("Browsing context","browsing context group")}}  (BCG) or in a new browsing context group.

When opened in a new BCG, any references between the new document and its opener are severed, and the new document may be process-isolated from its opener. This ensures that potential attackers can’t open your documents with {{domxref("Window.open()")}}  and then use the returned value to access its global object, and thereby prevents a set of cross-origin attacks referred to as XS-Leaks.

It also means that any object opened by your document in a new BCG can’t access it using window.opener. This allows you to have more control over references to a window than rel=noopener, which affects outgoing navigations but not documents opened with {{domxref("Window.open()")}} .

The behaviour depends on the policies of both the new document and its opener, and whether the new document is opened following a navigation or using {{domxref("Window.open()")}} .

Header type `{{Glossary("Response header")}}` 
`{{Glossary("Forbidden header name")}}`  No

Syntax

Cross-Origin-Opener-Policy: unsafe-none
Cross-Origin-Opener-Policy: same-origin-allow-popups
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Opener-Policy: noopener-allow-popups

Directives

Description

Generally you should set your policies such that only same-origin and trusted cross-origin resources that need to be able to script each other should be allowed to be opened in the same browser context group. Other resources should be cross-origin isolated in their own group.

The following sections show whether documents will be opened in the same BCG or a new BCD following a navigation or opening a window programmatically.

[!NOTE] The specification uses the term “popup” to refer to any document opened using {{domxref("Window.open()")}} , whether it is a popup, tab, window, or other context.

When navigating between documents, the new document is opened in the same BCG if the two documents have “matching coop policies”, and otherwise into a new BCG.

The policies match if:

The table below shows the result of this rule on whether documents are opened in the same or a new BCG for the different directive values.

Opener (row) / Opened (col) unsafe-none same-origin-allow-popups same-origin noopener-allow-popups
unsafe-none Same New New New
same-origin-allow-popups New Same if same-origin New New
same-origin New New Same if same-origin New
noopener-allow-popups New New New Same if same-origin

Opening with Window.open()

When opening a document using Window.open(), the new document is opened in the same BCG according to the following rules, which are evaluated in order:

  1. True: opened noopener-allow-popups
  2. False: (opener same-origin-allow-popups or noopener-allow-popups) and (opened document is unsafe-none)
  3. False: Matching COOP policies (as outlined above for navigations)
  4. True: Otherwise!

The table below shows the opener behaviour for the different directive values.

Opener (row) / Opened (col) unsafe-none same-origin-allow-popups same-origin noopener-allow-popups
unsafe-none Same New New New
same-origin-allow-popups Same Same if same-origin New New
same-origin New New Same if same-origin New
noopener-allow-popups Same New New New

Examples

Features that depend on cross-origin isolation

Certain features, such as access to {{jsxref("SharedArrayBuffer")}}  objects or using {{domxref("Performance.now()")}}  with unthrottled timers, are only available if your document is {{domxref("Window.crossOriginIsolated","cross-origin isolated","","nocode")}} .

To use these features in a document, you will need to set the COOP header to same-origin and the {{HTTPHeader("Cross-Origin-Embedder-Policy")}}  header to require-corp (or credentialless). In addition the feature must not be blocked by {{HTTPHeader("Permissions-Policy/cross-origin-isolated","Permissions-Policy: cross-origin-isolated")}} .

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

You can use the {{domxref("Window.crossOriginIsolated")}}  and {{domxref("WorkerGlobalScope.crossOriginIsolated")}}  properties to check if a document is cross-origin isolated, and hence whether or not the features are restricted:

const myWorker = new Worker("worker.js");

if (crossOriginIsolated) {
  const buffer = new SharedArrayBuffer(16);
  myWorker.postMessage(buffer);
} else {
  const buffer = new ArrayBuffer(16);
  myWorker.postMessage(buffer);
}

Severing the opener relationship

Consider a hypothetical origin example.com that has two very different applications on the same origin:

The administrators of the “passwords” application would very much like to ensure that it can’t be directly scripted by the “chat” app, which by its nature has a larger XSS surface. The “right way” to isolate these applications would be to host them on different origins, but in some cases that’s not possible, and those two applications have to be on a single origin for historical, business, or branding reasons.

The Cross-Origin-Opener-Policy: noopener-allow-popups header can be used to ensure that a document can’t be scripted by a document that opens it.

If example.com/passwords is served with noopener-allow-popups the WindowProxy returned by {{domxref("Window.open()")}}  will indicate that the windows is closed ({{domxref("Window.closed")}}  is true), so the opener can’t script the passwords app:

const handle = window.open("example.com/passwords", "passwordTab");
if (windowProxy.closed) {
  // The new window is closed so it can't be scripted.
}

Note that this alone is not considered a sufficient security measure. The site would also need to do the following:

Specifications

{{Specifications}} 

Browser compatibility

{{Compat}} 

See also

In this article

View on MDN