tl;dr:
Browsers enforce the same-origin policy for many website-initiated fetches. However, in some contexts, the same origin policy does not apply. For example, a page may load images from other origins. The specification refers to these as requests with a “no-cors” request mode.
Meanwhile, the “Spectre” family of attacks allow a website to read memory within an operating system process. (Caveats apply and it‘s more complicated that that; but that’s the gist.)
These, at its extreme, allow a near-complete circumvention of the “same-origin policy”: By first loading any resource one wishes to read via e.g. an <img>
tag, and then reading the result from its own memory via a “Spectre” gadget. In this scenario, the image loading will fail and the site does not get any programmatic access to the image content. (That is, to the bytes of the resource, that the attacker pretended to be an image.) But because the “image” has been brought into the renderer process (in order to parse it), and because “Spectre” allows access to memory within the process, an attacking page might get its contents after all.
Additionally, CORB/ORB serve as a “defense in depth” measure: They help to improve isolation between origins and thus make it harder to exploit a compromised renderer.
In brief, the security property we want from CORB/ORB is this: For any “no-cors” request we want positive evidence that the response received is of the intended data type.
Note:
Both CORB and ORB are deprecations at heart. That is: Formerly allowed behaviour would be newly disallowed and blocked. This invariably causes issues for some well-meaning websites that, often inadvertently, rely on the behaviour to be deprecated. Any deprecation requires great care when deploying in order to minimize unintended side-effects on the web ecosystem.
Cross-Origin Read Blocking identifies a number of resource types that should be protected, namely HTML, XML (except SVG), and JSON, and blocks them from being loaded in “no-cors” responses. None of the intended usages for these resource types issue “no-cors” requests. In addition to MIME type checks, it also employs “sniffers” for these formats.
The full details are more complicated. Here, we'll skip over details of sniffing, error handling, and partial content responses (HTTP 206 responses). Additional details can be found here and here.
Note that this is a partial mismatch for our security requirements: Instead of requiring positive evidence for the intended format, we instead picked a handful of known-bad cases. Essentially, we look for negative evidence for a request type mismatch, and ignore all the cases for which we don't have such evidence.
ORB is an alternative proposal to solve the same problem. In Chromium we intend to replace CORB with ORB, so that in the context of Chromium ORB could be considered as a “version 2” of CORB.
The fundamental difference between CORB and ORB is that CORB picked specific type mismatches to disallow, while ORB enumerates the data formats that we expect to occur in “no-cors” requests and blocks the rest. This makes ORB a better fit for our security requirements. It also makes ORB a much bigger risk for web compatibility.
Since CORB/ORB are deprecations, great care must be taken to not break legitimate web sites. Since no implementation of ORB exists (as of 2022-05), we have no existing web compatibiltiy data and must thus be careful in deploying ORB.
As a first step we are implementing a subset, dubbed “ORB v0.1”. This differs from ORB as proposed:
audio/*
, video/*
, and some XML MIME types.One unfortunate effect of postponing JSON and JavaScript sniffing is that “ORB v0.1” does not yet achieve our goal of blocking any resource for which we do not have positive evidence.
These plans are not settled. We will iterate towards a more complete ORB implementation. Note that some ORB details are also not finalized yet.
The main difference is that “ORB v0.1” is more permissive, to reduce web compatibility risks. A more detailed write-up may be found here.
Below are the tabulated differences between “ORB v0.1” and the ORB proposal. Decisions are based on four factors:
“ORB v0.1” | ORB | Comment | |
---|---|---|---|
MIME type: JavaScript | n/a (allow, unless it “sniffs” wrong. This follows from the rules below.) | allow (without sniffing) | Known-good “no-cors” MIME types. |
MIME type: HTML, JSON, XML, text/plain | block (if nosniff) | block (if nosniff) | MIME types that have historically been accepted in “no-cors” requests. We hope developers set the “nosniff” header. |
MIME type: zip + gzip, various MS office types; protobuf, text/csv | block | block | “Never sniff” MIME types. Not allowed in any “no-cors” requests. |
MIME type: audio/* or video/* | allow | block (unless it “sniffs” okay. This follows from the rules below. I'd expect most resources to “sniff” okay, though, so in practice these would likely be mostly allowed.) | “ORB v0.1” relaxes audio + video handling, and just lets all audio + video MIME types pass. |
MIME type: n/a (invalid/missing MIME type) | n/a (rules below apply. Would probably mostly allow.) | allow | |
sniffs as audio/, video/, image/* | allow | allow | |
JSON / JS handling | block if first 1KiB bytes sniff as HTML (but not MIME type: CSS),XML (but not MIME type: SVG),JS parser breaker,or JSON. | block if “nosniff”, allow if parses (!!) as JavaScript, block otherwise. (E.g. JSON or HTML or PDF won’t parse as JS.) | “ORB v0.1” makes a very deliberate decision to not parse a full response. |
default | allow | block | Because “ORB v0.1” can only “sniff” certain JS anti-patterns, it has to make the unfortunate decision to allow unknown content. We'd very much like to fix this, without the cost of a full parse. |
The table omits: