HTTP Headers
Cross Origin Opener Policy
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 hasunsafe-none
or no COOP directive.When using
Window.open()
, documents withunsafe-none
will always open documents with any other value into a new BCG. However, documents withunsafe-none
can be opened in the same BCG if the opener has a directive likesame-origin-allow-popups
,noopener-allow-popups
, orunsafe-none
. A document withsame-origin
will always open a document withunsafe-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 thesame-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 ofunsafe-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 withsame-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 haveunsafe-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-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 |
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:
- If the new document has COOP set to
noopener-allow-popups
, it opens in a new BCG. - If it has COOP set to
unsafe-none
and the opener document’s COOP is eithersame-origin-allow-popups
ornoopener-allow-popups
, it opens in the same BCG. - If both documents have matching COOP policies, it opens in the same BCG.
- 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-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 |
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.
You can check if a document is cross-origin isolated using properties like Window.crossOriginIsolated and WorkerGlobalScope.crossOriginIsolated.
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.
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
orBroadcastChannel
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:
- Install and open the Requestly Chrome extension. You can find it on the Chrome Web Store.
- Create a new rule: Click on “Create Rule” and choose “Modify Headers” from the list of available rule types.
- 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).
- Set the URL condition: Specify the URL or pattern where this header change should apply (e.g., https://your-website.com/*).
- 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.
Table of Contents
- No headings found.