Use COOP and COEP to set up a cross-origin isolated environment and enable powerful features like SharedArrayBuffer
, performance.measureUserAgentSpecificMemory()
and high resolution timer with better precision.
Updates
- June 21, 2022: Worker scripts also need care when cross-origin isolation is enabled. Added some explanations.
- Aug 5, 2021: JS Self-Profiling API has been mentioned as one of APIs that require cross-origin isolation, but reflecting recent change of the direction, it's removed.
- May 6, 2021: Based on feedback and issues reported we've decided to adjust
the timeline for
SharedArrayBuffer
usage in none cross-origin isolated sites to be restricted in Chrome M92. - April 16, 2021: Added notes about a new COEP credentialless mode and COOP same-origin-allow-popups to be a relaxed condition for cross-origin isolation.
- March 5, 2021: Removed limitations for
SharedArrayBuffer
,performance.measureUserAgentSpecificMemory()
, and debugging functionalities, which are now fully enabled in Chrome 89. Added upcoming capabilities,performance.now()
andperformance.timeOrigin
, that will have higher precision. - February 19, 2021: Added a note about feature policy
allow="cross-origin-isolated"
and debugging functionality on DevTools. - October 15, 2020:
self.crossOriginIsolated
is available from Chrome 87. Reflecting that,document.domain
is immutable whenself.crossOriginIsolated
returnstrue
.performance.measureUserAgentSpecificMemory()
is ending its origin trial and is enabled by default in Chrome 89. Shared Array Buffer on Android Chrome will be available from Chrome 88.
Some web APIs increase the risk of side-channel attacks like Spectre. To mitigate that risk, browsers offer an opt-in-based isolated environment called cross-origin isolated. With a cross-origin isolated state, the webpage will be able to use privileged features including:
API | Description |
---|---|
SharedArrayBuffer
|
Required for WebAssembly threads. This is available from Android Chrome 88. Desktop version is currently enabled by default with the help of Site Isolation, but will require the cross-origin isolated state and will be disabled by default in Chrome 92. |
performance.measureUserAgentSpecificMemory()
|
Available from Chrome 89. |
performance.now() , performance.timeOrigin
|
Currently available in many browsers with the resolution limited to 100 microseconds or higher. With cross-origin isolation, the resolution can be 5 microseconds or higher. |
The cross-origin isolated state also prevents modifications of
document.domain
. (Being able to alter document.domain
allows communication
between same-site documents and has been considered a loophole in the
same-origin policy.)
To opt in to a cross-origin isolated state, you need to send the following HTTP headers on the main document:
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
These headers instruct the browser to block loading of resources or iframes which haven't opted into being loaded by cross-origin documents, and prevent cross-origin windows from directly interacting with your document. This also means those resources being loaded cross-origin require opt-ins.
You can determine whether a web page is in a cross-origin isolated state by
examining
self.crossOriginIsolated
.
This article shows how to use these new headers. In a follow-up article I will provide more background and context.
Deploy COOP and COEP to make your website cross-origin isolated
Integrate COOP and COEP
1. Set the Cross-Origin-Opener-Policy: same-origin
header on the top-level document
By enabling COOP: same-origin
on a top-level document, windows with the same
origin, and windows opened from the document, will have a separate browsing
context group unless they are in the same origin with the same COOP setting.
Thus, isolation is enforced for opened windows and mutual communication between
both windows is disabled.
A browsing context group is a set of windows that can reference each other. For
example, a top-level document and its child documents embedded via <iframe>
.
If a website (https://a.example
) opens a popup window (https://b.example
),
the opener window and the popup window share the same browsing context, therefore
they have access to each other via DOM APIs such as window.opener
.
You can check if the window opener and its openee are in separate browsing context groups from DevTools.
2. Ensure resources have CORP or CORS enabled
Make sure that all resources in the page are loaded with CORP or CORS HTTP headers. This step is required for step four, enabling COEP.
Here is what you need to do depending on the nature of the resource:
- If the resource is expected to be loaded only from the same origin, set
the
Cross-Origin-Resource-Policy: same-origin
header. - If the resource is expected to be loaded only from the same site but cross
origin, set the
Cross-Origin-Resource-Policy: same-site
header. - If the resource is loaded from cross origin(s) under your control, set the
Cross-Origin-Resource-Policy: cross-origin
header if possible. - For cross origin resources that you have no control over:
- Use the
crossorigin
attribute in the loading HTML tag if the resource is served with CORS. (For example,<img src="***" crossorigin>
.) - Ask the owner of the resource to support either CORS or CORP.
- Use the
- For iframes, follow the same principles above and set the
Cross-Origin-Resource-Policy: cross-origin
(orsame-site
,same-origin
depending on the context). - Scripts loaded with a
WebWorker
must be served from same-origin, so you don't need a CORP or CORS headers. - For a document or a worker served with
COEP: require-corp
, cross-origin subresources loaded without CORS must set theCross-Origin-Resource-Policy: cross-origin
header to opt into being embedded. For example, this applies to<script>
,importScripts
,<link>
,<video>
,<iframe>
, etc.
3. Use the COEP Report-Only HTTP header to assess embedded resources
Before fully enabling COEP, you can do a dry run by using the
Cross-Origin-Embedder-Policy-Report-Only
header to examine whether the policy
actually works. You will receive reports without blocking embedded content.
Recursively apply this to all documents including the top-level document, iframes and worker scripts. For information on the Report-Only HTTP header, see Observe issues using the Reporting API.
4. Enable COEP
Once you've confirmed that everything works, and that all resources can be
successfully loaded, switch the Cross-Origin-Embedder-Policy-Report-Only
header to the Cross-Origin-Embedder-Policy
header with the same value to all
documents including those that are embedded via iframes and worker scripts.
Determine whether isolation succeeded with self.crossOriginIsolated
The self.crossOriginIsolated
property returns true
when the web page is in a
cross-origin isolated state and all resources and windows are isolated within
the same browsing context group. You can use this API to determine whether you
have successfully isolated the browsing context group and gained access to
powerful features like performance.measureUserAgentSpecificMemory()
.
Debug issues using Chrome DevTools
For resources that are rendered on the screen such as images, it's fairly easy
to detect COEP issues because the request will be blocked and the page will
indicate a missing image. However, for resources that don't
necessarily have a visual impact, such as scripts or styles, COEP issues might
go unnoticed. For those, use the DevTools Network panel. If
there's an issue with COEP, you should see
(blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)
in the Status
column.
You can then click the entry to see more details.
You can also determine the status of iframes and popup windows through the Application panel. Go to the "Frames" section on the left hand side and expand "top" to see the breakdown of the resource structure.
You can check the iframe's status such as availability of SharedArrayBuffer
,
etc.
You can also check the popup windows's status such as whether it's cross-origin isolated.
Observe issues using the Reporting API
The Reporting API is another mechanism through which you can detect various issues. You can configure the Reporting API to instruct your users' browser to send a report whenever COEP blocks the loading of a resource or COOP isolates a pop-up window. Chrome has supported the Reporting API since version 69 for a variety of uses including COEP and COOP.
To learn how to configure the Reporting API and set up a server to receive reports, head over to Using the Reporting API.
Example COEP report
An example COEP report payload when cross-origin resource is blocked looks like this:
[{
"age": 25101,
"body": {
"blocked-url": "https://third-party-test.glitch.me/check.svg?",
"blockedURL": "https://third-party-test.glitch.me/check.svg?",
"destination": "image",
"disposition": "enforce",
"type": "corp"
},
"type": "coep",
"url": "https://cross-origin-isolation.glitch.me/?coep=require-corp&coop=same-origin&",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36"
}]
Example COOP report
An example COOP report payload when a pop-up window is opened isolated looks like this:
[{
"age": 7,
"body": {
"disposition": "enforce",
"effectivePolicy": "same-origin",
"nextResponseURL": "https://third-party-test.glitch.me/popup?report-only&coop=same-origin&",
"type": "navigation-from-response"
},
"type": "coop",
"url": "https://cross-origin-isolation.glitch.me/coop?coop=same-origin&",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]
When different browsing context groups try to access each other (only on
"report-only" mode), COOP also sends a report. For example, a report when
postMessage()
is attempted would look like this:
[{
"age": 51785,
"body": {
"columnNumber": 18,
"disposition": "reporting",
"effectivePolicy": "same-origin",
"lineNumber": 83,
"property": "postMessage",
"sourceFile": "https://cross-origin-isolation.glitch.me/popup.js",
"type": "access-from-coop-page-to-openee"
},
"type": "coop",
"url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
},
{
"age": 51785,
"body": {
"disposition": "reporting",
"effectivePolicy": "same-origin",
"property": "postMessage",
"type": "access-to-coop-page-from-openee"
},
"type": "coop",
"url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]
Conclusion
Use a combination of COOP and COEP HTTP headers to opt a web page into a special
cross-origin isolated state. You will be able to examine
self.crossOriginIsolated
to determine whether a web page is in a cross-origin
isolated state.
We'll keep this post updated as new features are made available to this cross-origin isolated state, and further improvements are made to DevTools around COOP and COEP.