To be clear, SharedArrayBuffer
is an issue because it can be used as part of Spectre/Meltdown side-channel attack exploits against the client. JavaScript running in a webpage that has access to this feature may be able to utilise it to leak information from memory. For this to be a problem, the following prerequisites must be true:
- An attacker must run malicious JavaScript in a webpage
- The system running the JavaScript code must be vulnerable to Spectre/Meltdown
- That webpage must be configured with a policy that enables
SharedArrayBuffer
so that it can be used to aid exploitation of the vulnerability
The SharedArrayBuffer
functionality is only really useful here because it provides access to a convenient segment of memory that can be shared across threads. It isn't inherently dangerous, it's just a useful primitive for cache side-channel attacks.
Cross-process attacks with Spectre/Meltdown have largely been mitigated with OS patches and microcode updates. However, the side-channel attacks can still be used to leak information from the process to itself. This is normally not a problem, because the whole program is executing with the same security context, but in a browser this is problematic because origins should not be able to access resources from each other without explicit permission.
When Cross-Origin-Opener-Policy: same-origin
is used, the browser isolates the origin (webpage that set the header) in its own process and browsing context. Cross-origin resources are not loaded into the same execution context (process) as the origin, so if the cross-origin resources exploit Spectre/Meltdown they won't be able to access information from the origin.
CORS normally blocks XHR / Fetch API requests for remote resources, but it doesn't prevent you from just including a cross-origin resource in a HTML tag, like an image. Certain resources such as frames have their contents isolated from the origin, but others aren't. Some side-channel exploits utilise images and other resources to sidestep CORS in this way. The origin can protect against this to some degree using CSP, but that doesn't help a cross-origin from having its resources embedded.
The Cross-Origin-Embedder-Policy: require-corp
header builds on top of the standard CORS policy and Access-Control-Allow-Origin
header, expanding it to include all forms of resources instead of just scripts. This allows a cross-origin to prevent its resources (e.g. scripts and images) from being embedded in a different origin.
When a resource response combines COOP with COEP, code executing in that resource's origin is isolated and cannot load cross-origin resources, and other origins cannot load that resource as cross-origin either. Making both a requirement means that any script with access to SharedArrayBuffer
will either be loaded from the origin and trusted, but executed in its own isolated context, or loaded from an explicitly trusted cross origin, and again executed in its own isolated context.
If you utilise the service workers trick to set the COOP and COEP headers as the request comes in, this doesn't negatively impact security. You're turning on the security measures that allow SharedArrayBuffer
to be used safely. An attacker can still exploit Spectre/Meltdown with it, but they can only steal secrets from their own isolated execution context, which is pointless. If the cross-origin already sets the COOP and COEP HTTP response headers, they're processed and enforced by the browser before they get to your service worker, meaning that you won't be able to tamper with them.