blob: 7aed551ff9b44d46476240453d631cf1563c3393 [file] [view]
# Security for Agents
This document describes the fundamental security architecture and assumptions of
Chromium, which is called the "security model" of Chromium. It also describes
common types of violations of that model, which are attacks against Chromium.
Some parts of this document make reference to V8 as well. V8 can be built as a
standalone tool called "d8", which is useful for finding or demonstrating some
kinds of attacks.
Notes for humans: this document is **not** part of the VRP rules or guidelines;
it is advice for AI agents auditing Chromium for bugs.
## Security Architecture
### Processes & Sandboxing
Chromium is separated into several processes, including the browser process, the
GPU process, the network service process, and potentially many renderer and
utility processes. Each process except the browser process is inside a
"sandbox", which uses primitives supplied by the OS to constrain what that
process can do. The sandbox is different for each type of process. Renderer and
utility processes have the strongest sandbox, the network and GPU processes have
weaker sandboxes, and the browser process has no sandbox at all.
Communication between processes happens over an IPC system named Mojo. Mojo
sends messages between processes, with serialization and deserialization at
either end, and can also pass file handles and some other kinds of object
between processes. Mojo allows for interprocess calls to methods grouped
together into interfaces, and not all interfaces are available to all callers.
### Web Security
The fundamental unit of isolation on the web is the "origin". A "page" is the
contents of a tab, which may be composed of content from multiple origins
combined together. In general, scripts or other content from one origin
shouldn't affect or see scripts or content from another origin, unless both
origins opt into sharing.
Inside Chromium, a WebContents represents a single loaded page, and may contain
content from multiple origins which are hosted in separate RenderFrames.
RenderFrames that are in different origins are usually in separate renderer
processes, isolated from each other.
When discussing attacks across origins, we sometimes use the example origins
"evil.com" to mean an attacker's origin, and "good.com" to mean an origin they
are trying to steal or corrupt data from. In this context, both origins are
generally assumed to be loaded in Chromium at the same time, but in separate
frames.
### Javascript & Webassembly
Chromium exposes several ways for websites to run their own code on the user's
machine. The two most common are Javascript and Webassembly. V8 is responsible
for handling both of these, and V8 should ensure that code supplied by websites
isn't able to have dangerous effects inside the renderer process, like
corrupting memory or causing a use-after-free of an object.
V8 compiles Javascript or Webassembly into native code to be executed by the
CPU. V8 must guarantee that that native code it generates doesn't break certain
safety properties, such as being unable to overwrite data structures that aren't
meant to be exposed to Javascript.
### Builds & Invariants
There are a few different possible build configurations of Chromium or of V8.
The three that are most relevant for security purposes are:
* "Release", which means `is_asan=false is_debug=false` in args.gn
* "Debug", which means `is_asan=false is_debug=true` in args.gn
* "ASAN", which means `is_asan=true is_debug=false` in args.gn
There are several different ways that invariants in Chromium and V8 are
enforced. The CHECK macro enforces an invariant even in released builds, and the
DCHECK macro enforces an invariant in debug builds only. Some kinds of invariant
violation, like indexing outside the bounds of a base::span, are also detected
in release builds and cause an immediate crash.
## Attacks
Every attack comes with a series of steps, which are generally supplied as a
short program, called a "proof of concept". A "proof of concept" provides
evidence that a bug is present, and is not the same thing as an "exploit", which
makes use of a bug to achieve a malicious goal. A "proof of concept" is by
definition harmless, but should have some objective and verifiable external
effects to demonstrate that the bug is present.
A security bug report (or vulnerability report) is a description of how to
execute an attack. Every security bug report must take the form: "An attacker
can cause Chromium to [something which harms the user] by [attack steps]." For
example:
* An attacker can cause Chromium to _execute arbitrary code in the renderer
sandbox_ by _calling `window.foo(12345)`_.
* An attacker can cause Chromium to _execute arbitrary code in the browser
process_ by _calling Mojo API `foo()`_.
* An attacker can cause Chromium to _disclose a cookie from good.com_ by
_loading it in an iframe with the `foo` attribute set to `bar`_.
Unless you can clearly describe both the security harm to the user, and the
attack steps, you do not have a security bug report.
### Escalated Code Execution
A security bug that allows for execution of arbitrary code of an attacker's
choice outside of any sandbox (so in the browser process or elsewhere in the OS
outside of Chromium) or in a sandbox weaker than the renderer sandbox (some
target process) is the most severe category of attack. These bugs generally take
two forms:
* Bugs in the [something] process that are reachable over IPC from the renderer
process
* Bugs in the operating system itself that are reachable from inside the
renderer sandbox
For this kind of bug, the proof of concept must either:
* Cause the target process (which may be the browser process) to crash with an
ASAN failure indicating an out-of-bounds read, out-of-bounds write,
use-after-free, or use-after-poison, or
* Cause the target process to directly execute attacker-supplied machine code,
or
* Cause an operating system service to crash, or
* Cause the operating system to execute an attacker-chosen program with
attacker-supplied arguments
To simulate a compromised renderer process, use the MojoJS feature by passing
`--enable-features=MojoJS` to Chromium. This allows you to call Mojo methods
from JavaScript. If that does not work for some reason, the proof of concept
**may** be in the form of a patch intended to apply to the Chromium source tree.
If so, this patch must modify code that is only executed in the renderer, to
simulate a compromised renderer process.
Anything that does not lead to one of these consequences is almost certainly not
a valid proof of concept for an escalated code execution bug.
### Renderer Code Execution
A security bug that allows for execution of arbitrary code of an attacker's
choice inside the renderer sandbox is a renderer code execution bug. These bugs
generally take two forms:
* Bugs in the implementation of Chromium that allow a crafted webpage to corrupt
memory
* Bugs in the implementation of V8 that cause a crafted Javascript or
Webassembly program to be compiled into code which corrupts memory when run
For V8, code compiled from attacker-supplied Javascript or Webassembly is
executed inside a "heap sandbox", which confines memory reads and writes
performed by that compiled code to a certain region. Bugs which allow for
reading or writing memory outside the heap sandbox are "heap sandbox escapes"
and are very valuable bugs. Bugs which allow for reading or writing memory
inside the heap sandbox are less valuable but still valuable.
For this kind of bug, the proof of concept must either:
* Cause the renderer process to crash with an ASAN failure indicating an
out-of-bounds read, out-of-bounds write, use-after-free, or use-after-poison,
or
* Cause a debug renderer to crash with a DCHECK failure from V8
* Cause an ASAN build of d8 to crash with an ASAN failure
* Cause a debug build of d8 to crash with a DCHECK failure
Not all DCHECK failures in V8 or d8 are security bugs, but many are, so to be
conservative we assume that all of them are security bugs until we are confident
they are not.
### Cross-Site Bugs
A security bug that allows for one origin to either read data from another
origin or run code in another origin is a cross-site bug. There are some
intentional ways to share data between origins, but by default origins shouldn't
be able to interact.
A proof of concept of a cross-site bug must show that:
* evil.com can figure out whether the user has visited a specific URL on
good.com
* evil.com can learn some text from the body of good.com that would only be
visible with the user's cookies
* evil.com can cause a script of its choice to run in good.com's renderer
* evil.com can get the value of a cookie set for good.com
### Extension Bugs
A bug which allows an extension to take actions it shouldn't be able to is an
extension security bug. Extensions have permissions defined in their
manifest.json, and all extensions have certain implicit permissions like the
ability to make network requests in their own context.
For this kind of bug, the proof of concept is an extension which, when loaded,
takes an action the extension should not be able to take.
### Other Bugs
Any other bug which allows a website to cause Chromium to harm a user may be a
security bug, even if it doesn't fit one of these categories. Any such bug needs
a **clear** explanation of the security consequences of the bug, as well as who
can exploit it. Such a bug also needs clear reproduction steps or an executable
proof of concept.
## Non-Bugs
There are some common kinds of reports which are **not** security bugs in
Chromium:
* CHECK failures
* DCHECK failures outside V8
* Out-of-bounds accesses of STL containers or base::span via operator[]
* Null pointer reads and writes with small offsets (<= 32 KiB)
* MiraclePtr-protected use-after-frees (those with "MiraclePtr Status:
PROTECTED")
* Denial-of-service bugs, including resource exhaustion and browser/GPU hangs
* Stack overflows
* Bypasses of enterprise policies
* Downloads not being classified as dangerous
* Any attack assuming local administrator access to the user's machine
* Any attack assuming a remote debug protocol connection to Chromium
* Bugs in other apps reachable via Intents or external URL handlers from
Chromium
* Bugs in dependencies of Chromium which are not reachable in Chromium itself
* Bugs in tests
* Causing AI features in Chromium to emit misleading or harmful output by
entering a crafted prompt
* Bugs that use an unsupported flag or feature, including:
* `--single-process`
* any flag whose name contains `unsafe`
* SwiftShader
## Reporting Bugs
When reporting a bug:
* Do not log _anything_ as part of your proof of concept. If your bug is
legitimate, it must have external, observable consequences as described above.
Log messages can be misleading, and we will ignore them when assessing your
bug.
* Do not include stack traces which do not have symbol names. We cannot use
these to debug or reproduce the report.
* Do not include your evaluations of CVSS scores or similar. Chromium uses a
project-specific framework to evaluate severities and we ignore CVSS estimates
from reporters.
* Do include these sections:
* Written description of attack steps
* ASAN stack trace or debug crash report, if relevant
* A short description of the security consequences of the attack, using the
terms given above
* Which revision, build arguments (args.gn), and command-line flags you
supplied
* Your proof of concept should be a single file:
* For bugs that reproduce via d8, a single Javascript source file called
"poc.js"
* For bugs that reproduce via loading in Chromium, a single HTML source file
called "poc.html"
* For bugs that reproduce via loading in Chromium, but which cannot be
served as a single HTML file, a single Python source file called "poc.py"
which, when invoked with a port number, will run a web server on localhost
with that port number. That web server must serve any needed exploit code
when /poc.html is loaded from it.
* For bugs that simulate a compromised renderer with a source patch, a
single unified diff called "poc.patch". This patch must only change code
that runs in the renderer.
* For bugs that have a demonstration video, a single mp4 file called
"poc.mp4".
* If you are reporting an extension security bug specifically, attach **all the
files contained in the extension separately**, along with the zipped extension (a .crx file).
* You may also include your root-cause analysis, if you have one:
* Identify the file, line, and function in Chromium which contain the bug
* Identify which Chromium commit you analyzed to find the bug
* Identify which Chromium commit introduced the bug
In general, a shorter bug report is better. Bug reports should be as short as
possible, but no shorter.
## Further Reading
The docs/security directory contains other security-related documentation. You
should also consult the README.md and SECURITY.md files for the directories you
are looking for bugs in, if they are present.