🎉 Requestly joins BrowserStack to build the future of application testing. Read more

HTTP Headers

Cross Origin Opener Policy

HTTP Header

The HTTP Cross-Origin-Opener-Policy (COOP) response header enables a website to specify whether a new top-level document, opened using Window.open() or by navigating to a different page, should be loaded in the same browsing context group (BCG) or in a separate one.

When a document opens in a new BCG, all references between the new document and its opener are severed, effectively isolating the new document from its opener’s process.
This prevents potential attackers from exploiting window references to access sensitive data, helping to mitigate various cross-origin attacks known as XS-Leaks.

Furthermore, if a document is opened in a new BCG, it cannot access its opener via window.opener.
This level of control enhances security by limiting window interactions, surpassing what rel=noopener offers—this attribute only affects navigations initiated with links, not documents opened with Window.open().

The actual behavior is influenced by the security policies of both the newly opened document and its opener, and whether the document was opened through navigation or via Window.open().

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

unsafe-none

The document allows sharing its browsing context group with any other document, which can be unsafe. It is used to opt-out a document from using COOP for process isolation. This is the default setting.

During navigation, documents with unsafe-none will always open in and be opened into a new browsing context group (BCG), unless the other document also has unsafe-none or no COOP directive.

When using Window.open(), documents with unsafe-none will always open documents with any other value into a new BCG. However, documents with unsafe-none can be opened in the same BCG if the opener has a directive like same-origin-allow-popups, noopener-allow-popups, or unsafe-none. A document with same-origin will always open a document with unsafe-none into a new BCG.

same-origin

This directive permits loading into BCGs that use COOP and contain only same-origin documents. It is used to provide cross-origin isolation for a BCG.

Documents with same-origin will only open and be opened in the same BCG if both are same-origin and have the same-origin directive.

same-origin-allow-popups

This directive is similar to same-origin, but it allows opening documents with Window.open() in the same BCG if they have a COOP value of unsafe-none.

It is used to relax the same-origin restriction in cases where a document needs the benefits of cross-origin isolation but also needs to open and maintain references to trusted cross-origin documents, such as during OAuth or payment transactions.

A document with this directive can open another in the same BCG using Window.open() if the other has unsafe-none. In this case, it doesn’t matter if the opened document is cross-site or same-site. Otherwise, documents with same-origin-allow-popups will open and be opened in the same BCG only if both are same-origin and have this directive.

noopener-allow-popups

Documents with this directive are always opened into a new BCG, except when they are opened via navigation from a document that also has noopener-allow-popups.

This directive supports cases where process-isolation of same-origin documents is required.

It isolates the new document from its opener, preventing scripts from running across contexts, regardless of the origin. This ensures the opener cannot control or manipulate the opened document, even if both are same-origin.

On navigation, a document with this directive will always open other documents in a new BCG unless they are same-origin and also have noopener-allow-popups. Using Window.open(), a document with this directive will open documents in a new BCG unless they have unsafe-none, in which case the origin doesn’t matter.

Example

Generally, your policies should be configured to allow only same-origin and trusted cross-origin resources that need scripting to be within the same browser context group (BCG).
Other resources should be cross-origin isolated in their own separate group.

The following sections discuss how documents are opened—either within the same BCG or in a new BCG—during navigation or programmatic window opening.

When navigating between documents, the new document will open in the same BCG if both documents share “matching coop policies.” Otherwise, the new document opens in a different BCG.

The policies match if both documents have the unsafe-none policy or if their policies are the same and both are same-origin.

The table below illustrates how different directive values influence whether documents are opened in the same or different BCGs based on these policies.

Opener (↓) / Opened (→)unsafe-nonesame-origin-allow-popupssame-originnoopener-allow-popups
unsafe-noneSameNewNewNew
same-origin-allow-popupsNewSame if same-originNewNew
same-originNewNewSame if same-originNew
noopener-allow-popupsNewNewNewSame if same-origin

In the case of opening a document with Window.open(), rules determine whether the new document is in the same or a new BCG, evaluated in order:

  1. If the new document has COOP set to noopener-allow-popups, it opens in a new BCG.
  2. If it has COOP set to unsafe-none and the opener document’s COOP is either same-origin-allow-popups or noopener-allow-popups, it opens in the same BCG.
  3. If both documents have matching COOP policies, it opens in the same BCG.
  4. Otherwise, it opens in a new BCG.

The following table demonstrates how these rules affect document opening behavior based on directive values.

Opener (↓) / Opened (→)unsafe-nonesame-origin-allow-popupssame-originnoopener-allow-popups
unsafe-noneSameNewNewNew
same-origin-allow-popupsSameSame if same-originNewNew
same-originNewNewSame if same-originNew
noopener-allow-popupsSameNewNewNew

Features that depend on cross-origin isolation, such as access to SharedArrayBuffer or use of Performance.now() with unthrottled timers, are only available if your document is cross-origin isolated.

To enable these features, set the Cross-Origin-Opener-Policy header to same-origin and the Cross-Origin-Embedder-Policy header to require-corp (or credentialless). Additionally, ensure that the Permissions-Policy header does not block cross-origin isolation.

Example headers

You can check if a document is cross-origin isolated using properties like Window.crossOriginIsolated and WorkerGlobalScope.crossOriginIsolated.

Check cross-origin isolation

Severing the opener relationship

Consider a hypothetical origin example.com hosting two different applications:

  • A chat application at /chat that allows users to contact and message each other.
  • A password management application at /passwords storing all user passwords.

To prevent the “chat” app from scripting the sensitive “passwords” app, the latter can be hosted with Cross-Origin-Opener-Policy: noopener-allow-popups.
When this header is set, the WindowProxy returned by Window.open() indicates that the new window is closed (Window.closed is true), meaning it cannot be scripted by the opener.

Opener relationship example

Note that this measure alone isn’t fully secure. Additional security practices include:

  • Using Fetch Metadata to block cross-origin requests to sensitive apps that are not navigation-related.
  • Ensuring cookies with HttpOnly attribute.
  • Preventing root-level Service Worker installation on less-sensitive apps.
  • Using postMessage or BroadcastChannel in the sensitive app carefully to avoid exposing sensitive data.
  • Serving the login page on a separate origin to enhance password autofill security.
  • Understanding that the browser may still run these applications in the same process, which could be vulnerable to Spectre-like attacks.

How to Modify Header using Requestly

Requestly is a powerful Chrome extension that allows you to modify HTTP headers, including the Cross-Origin-Opener-Policy header. This is especially useful for testing how your application handles cross-origin isolation and security policies during development or debugging. Steps to Modify Cross-Origin-Opener-Policy Header:

  1. Install and open the Requestly Chrome extension. You can find it on the Chrome Web Store.
  2. Create a new rule: Click on “Create Rule” and choose “Modify Headers” from the list of available rule types.
  3. Add a new header modification:
    • Under “Action”, select “Add” or “Override”.
    • In the “Header Name” field, enter Cross-Origin-Opener-Policy.
    • In the “Header Value” field, enter your preferred policy (e.g., same-origin).
  4. Set the URL condition: Specify the URL or pattern where this header change should apply (e.g., https://your-website.com/*).
  5. Save the rule.

Once set up, Requestly will inject the Cross-Origin-Opener-Policy header into all matching requests, allowing you to test how your site manages cross-origin interactions and isolate the browsing context for enhanced security. Modifying the Cross-Origin-Opener-Policy header helps improve security by preventing other sites from opening your pages in a way that could lead to data leaks or attacks. Testing these settings ensures your web app properly isolates contexts to protect user data.