In Making your website "cross-origin isolated" using COOP and COEP we explained how to adopt to "cross-origin isolated" state using COOP and COEP. This is a companion article that explains why cross-origin isolation is required to enable powerful features on the browser.
The web is built on the same-origin policy: a security feature that restricts how documents and scripts can interact with resources from another origin. This principle restricts the ways websites can access cross-origin resources. For example, a document from
https://a.example is prevented from accessing data hosted at
However, the same-origin policy has had some historical exceptions. Any website can:
- Embed cross-origin iframes
- Include cross-origin resources such as images or scripts
- Open cross-origin popup windows with a DOM reference
If the web could be designed from scratch, these exceptions wouldn't exist. Unfortunately, by the time the web community realized the key benefits of a strict same-origin policy, the web was already relying on these exceptions.
The security side-effects of such a lax same-origin policy were patched in two ways. One way was through the introduction of a new protocol called Cross Origin Resource Sharing (CORS) whose purpose is to make sure that the server allows sharing a resource with a given origin. The other way is by implicitly removing direct script access to cross-origin resources while preserving backward compatibility. Such cross-origin resources are called "opaque" resources. For example, this is why manipulating the pixels of a cross-origin image via
CanvasRenderingContext2D fails unless CORS is applied to the image.
All these policy decisions are happening within a browsing context group.
For a long time, the combination of CORS and opaque resources was enough to make browsers safe. Sometimes edge cases (such as JSON vulnerabilities) were discovered, and needed to be patched, but overall the principle of not allowing direct read access to the raw bytes of cross-origin resources was successful.
This all changed with Spectre, which makes any data that is loaded to the same browsing context group as your code potentially readable. By measuring the time certain operations take, attackers can guess the contents of the CPU caches, and through that, the contents of the process' memory. Such timing attacks are possible with low-granularity timers that exist in the platform, but can be sped up with high-granularity timers, both explicit (like
performance.now()) and implicit (like
evil.com embeds a cross-origin image, they can use a Spectre attack to read its pixel data, which makes protections relying on "opaqueness" ineffective.
Ideally, all cross-origin requests should be explicitly vetted by the server that owns the resource. If vetting is not provided by the resource-owning server, then the data will never make it into the browsing context group of an evil actor, and therefore will stay out of reach of any Spectre attacks a web page could carry out. We call it a cross-origin isolated state. This is exactly what COOP+COEP is about.
Under a cross-origin isolated state, the requesting site is considered less dangerous and this unlocks powerful features such as
performance.measureUserAgentSpecificMemory() and high resolution timers with better precision which could otherwise be used for Spectre-like attacks. It also prevents modifying
Cross Origin Embedder Policy #
Cross Origin Embedder Policy (COEP) prevents a document from loading any cross-origin resources that don't explicitly grant the document permission (using CORP or CORS). With this feature, you can declare that a document cannot load such resources.
To activate this policy, append the following HTTP header to the document:
require-corp keyword is the only accepted value for COEP. This enforces the policy that the document can only load resources from the same origin, or resources explicitly marked as loadable from another origin.
For resources to be loadable from another origin, they need to support either Cross Origin Resource Sharing (CORS) or Cross Origin Resource Policy (CORP).
Cross Origin Resource Sharing #
<img src="https://third-party.example.com/image.jpg" crossorigin>
For example, if this image resource is served with CORS headers, use the
crossorigin attribute so that the request to fetch the resource will use CORS mode. This also prevents the image from being loaded unless it sets CORS headers.
Similarly, you may fetch cross origin data through the
fetch() method, which doesn't require special handling as long as the server responds with the right HTTP headers.
Cross Origin Resource Policy #
Cross Origin Resource Policy (CORP) was originally introduced as an opt-in to protect your resources from being loaded by another origin. In the context of COEP, CORP can specify the resource owner's policy for who can load a resource.
Cross-Origin-Resource-Policy header takes three possible values:
Resources that are marked
same-site can only be loaded from the same site.
Resources that are marked
same-origin can only be loaded from the same origin.
Resources that are marked
cross-origin can be loaded by any website. (This value was added to the CORP spec along with COEP.)
Cross Origin Opener Policy #
Cross Origin Opener Policy (COOP) allows you to ensure that a top-level window is isolated from other documents by putting them in a different browsing context group, so that they cannot directly interact with the top-level window. For example, if a document with COOP opens a pop-up, its
window.opener property will be
null. Also, the
.closed property of the opener's reference to it will return
Cross-Origin-Opener-Policy header takes three possible values:
Documents that are marked
same-origin can share the same browsing context group with same-origin documents that are also explicitly marked
A top-level document with
same-origin-allow-popups retains references to any of its popups which either don't set COOP or which opt out of isolation by setting a COOP of
unsafe-none is the default and allows the document to be added to its opener's browsing context group unless the opener itself has a COOP of
If you want guaranteed access to powerful features like
performance.measureUserAgentSpecificMemory() or high resolution timers with better precision, just remember that your document needs to use both COEP with the value of
require-corp and COOP with the value of
same-origin. In the absence of either, the browser will not guarantee sufficient isolation to safely enable those powerful features. You can determine your page's situation by checking if
Learn the steps to implement this at Making your website "cross-origin isolated" using COOP and COEP.