How Chromium Uses CORB to Defend Against Spectre Attacks
This article provides a comprehensive overview of how the Chromium web browser implements Cross-Origin Read Blocking (CORB) to mitigate Spectre side-channel attacks. By inspecting network traffic before it reaches the webpage's rendering process, Chromium prevents sensitive cross-origin data—such as JSON, XML, and HTML—from ever entering the memory space where a Spectre attack could read it. Below, we break down the threat model of Spectre in the browser, the multi-process architecture of Chromium, and the exact steps CORB takes to sniff, evaluate, and strip sensitive data from unauthorized cross-origin requests.
The Spectre Threat to Web Browsers
Traditionally, web browsers relied on the Same-Origin Policy (SOP) to
keep websites isolated from one another. If evil.com
requested a sensitive file from bank.com using an
<img> or <script> tag, the browser
would fetch the file, place it into the renderer process memory, and
then rely on SOP to prevent evil.com from reading the
file's contents.
The discovery of the Spectre CPU vulnerability broke this security
model. Spectre allows malicious JavaScript to read arbitrary memory
within the same operating system process. Consequently, if
evil.com simply tricks the browser into loading
bank.com data into the shared renderer process memory, the
attacker can use a Spectre side-channel attack to read that data
directly from memory, completely bypassing the Same-Origin Policy.
Enter Cross-Origin Read Blocking (CORB)
To defeat Spectre, Chromium introduced Site Isolation, which places
different websites into separate operating system processes. However, an
attacker can still request cross-origin subresources (via
<img> or <script> tags) to pull
foreign data into their own renderer process.
Cross-Origin Read Blocking (CORB) is the defense mechanism designed to stop this. CORB prevents the browser from delivering sensitive cross-origin network responses to a renderer process unless the server explicitly permits it.
How Chromium Implements CORB
Chromium utilizes a multi-process architecture that separates the Network Process (which handles fetching data from the internet) from the Renderer Process (which executes JavaScript and renders the webpage). CORB operates entirely within the privileged Network Process, acting as a gatekeeper before data is passed to the untrusted Renderer Process.
Here is the step-by-step implementation of how CORB processes a cross-origin request:
1. Identifying Protected Data Types
CORB does not block all cross-origin traffic, because the web relies
on loading cross-origin images, stylesheets, and scripts. Instead, CORB
specifically targets data formats that contain sensitive information and
have no business being loaded into tags like <img> or
<script>. These protected MIME types are:
text/htmlapplication/xml(andtext/xml,application/xhtml+xml, etc.)application/json(andtext/json)
If a cross-origin response declares one of these MIME types, CORB flags it for further inspection.
2. Checking for CORS Exceptions
Before blocking a flagged resource, CORB checks if the cross-origin
request is actually legitimate. If the request was made using
Cross-Origin Resource Sharing (CORS)—for example, via a
fetch() or XMLHttpRequest call—and the
response includes valid Access-Control-Allow-Origin headers
permitting the requesting origin, CORB allows the data to pass through
to the renderer process.
3. Checking the
nosniff Header
If the request is not permitted by CORS, CORB checks if the server
included the X-Content-Type-Options: nosniff HTTP header.
If this header is present alongside a protected MIME type (HTML, XML, or
JSON), CORB immediately blocks the response without inspecting the
payload.
4. Content Sniffing
Web servers are frequently misconfigured. Sometimes a server will
label an image or a JavaScript file with a text/html MIME
type. If CORB blindly blocked everything labeled text/html,
it would break legitimate websites.
To prevent breaking the web, if the nosniff header is
absent, Chromium's Network Process performs "content sniffing." It reads
the first 1,024 bytes of the response body to verify if the content
actually matches the declared MIME type:
- For HTML: It looks for valid HTML tags (like
<!DOCTYPE html>,<html>,<head>,<script>,<iframe>). - For XML: It looks for the
<?xmldeclaration. - For JSON: It looks for valid JSON syntax (such as
starting with
{or[followed by a quotation mark) or a known JSON security prefix (often called a parser-breaker, like)]}').
If the sniffing confirms the file is genuinely HTML, XML, or JSON, CORB decides to block it. If the sniffing fails (meaning the file is likely a mislabeled image or script), CORB allows the file through to avoid breaking the webpage.
5. Stripping the Response (Sanitization)
When CORB decides to block a response, it does not simply cancel the network request, as doing so could leak information to the attacker about the existence of the file.
Instead, the Network Process sanitizes the response. It replaces the entire response body with an empty byte stream and strips away all HTTP headers (except for safe CORS-related headers). This empty, harmless response is then sent to the Renderer Process.
By stripping the data in the Network Process, the sensitive bytes never enter the memory space of the Renderer Process. Even if a malicious script successfully executes a Spectre attack within the renderer, the sensitive cross-origin data is simply not there to be stolen.