Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rust in Chromium

Decision

A one-time architectural or governance choice whose consequences still govern current work.

The decision to admit Rust as a production language for selected Chromium components, especially attacker-reachable parsers, so new high-risk code can satisfy the Rule of 2 without paying the cost of privileged C++ parsing in a separate process.

Rust in Chromium is a boundary decision, not a rewrite story. Selected new or replacement components may be written in Rust when they handle untrusted data, sit near privilege, and would otherwise need an extra utility process or a large C++ hardening budget. C++ remains Chromium’s dominant implementation language. Rust now has a governed production path when memory safety is the property doing the work.

Decision Statement

The Chromium project decided to support Rust in production, first through third-party Rust libraries called from C++ and then through first-party Rust libraries anywhere in chromium/src, so selected components can parse untrusted data with memory safety while still passing ordinary OWNERS review, Rust toolchain policy, crate-import review, and C++/Rust interop constraints.

Context

Chromium’s memory-safety problem is not marginal. The project’s security documentation reports that about 70% of High and Critical security bugs affecting Stable since 2015 were memory-unsafety bugs, and roughly half were use-after-free defects. V8 Heap Sandbox, MiraclePtr, spanification, CheckedNumeric APIs, fuzzing, and OS process isolation all respond after C++ is already in the design. The Rust decision addresses the new-code side of the same problem.

The project already had the Rule of 2: Chrome Security generally rejects designs that combine untrusted input, unsafe implementation language, and high privilege. The old escape routes were to reduce privilege with a utility process, prove the input trustworthy, or write the high-risk part in a memory-safe language available on the target platform. Rust made the third route cross-platform for Chromium.

The route became public in stages. In January 2023, the Chrome Security team announced support for third-party Rust libraries from C++ in Chromium, with a deliberately narrow interop direction and a stated decision not to open the whole tree to broad Rust contribution at once. Production-ready Rust toolchain support reached Chromium in M119. The current Rust documentation now says Rust can be used anywhere in the repository, subject to current interop capability and ordinary OWNERS approval. The first visible deployments follow the threat model: PNG, JSON, and web-font parsing have moved or are moving to Rust where the browser consumes complex input from the web.

Alternatives Considered

AlternativeDescriptionReason rejected
Keep new parser work in C++ and harden it locallyContinue writing parsers and decoders in C++, then apply fuzzing, checked arithmetic, spanification, MiraclePtr, sanitizer coverage, and OS process isolation.Necessary for existing code, but insufficient as the default for new high-risk parsing. The Rule of 2 still treats untrusted input plus unsafe language plus high privilege as a design failure.
Put every risky parser in a separate utility processReduce privilege instead of changing the implementation language. The parser remains C++, but it runs away from the browser or GPU process and returns a validated result over IPC.Effective, but expensive. Extra processes consume memory, add IPC boundaries, increase scheduling cost, and cost more on Android. Process isolation also doesn’t remove the C++ parser bug; it reduces what the bug can reach.
Rewrite large existing Chromium subsystems in RustTreat Rust as a replacement language for broad parts of Chromium: renderer internals, network stack, browser process services, or V8.Churn and interop cost dominate. Chromium is mostly C++, most stack frames remain C++, and broad rewrites would create years of cross-language boundary work before they retired enough C++ to pay for themselves. The 2023 public decision explicitly started narrower.
Admit Rust only as third-party leaf librariesUse Rust crates where their API is narrow, the dependency tree is controlled, and C++ calls into Rust without exposing Rust to arbitrary C++ object graphs.This was the first production path, and it remains a useful rule for crates. It was too narrow once the toolchain, GN integration, and interop story matured enough for first-party Rust libraries.
Admit Rust under ordinary Chromium governance with Rust-specific gatesAllow first-party and vetted third-party Rust code, require OWNERS approval, route first-party code through rust_static_library and chromium::import!, keep third-party crates under import review, and make unstable language features unsupported by default unless the Rust toolchain team agrees.Chosen. The policy lets Rust solve the memory-safety cases it is good at without turning the source tree into an ungated second-language experiment.

Rationale

Technically, Rust changes the Rule-of-2 calculation for new high-risk components. A parser that handles bytes from the network, a font embedded by a site, or an image supplied by untrusted content doesn’t become harmless because it is written in Rust. It still needs input validation, fuzzing, and review. But the default memory behavior is different: ordinary safe Rust removes use-after-free, out-of-bounds indexing, double free, and iterator invalidation as everyday parser defects. The design can spend its review budget on format correctness and trust-boundary behavior rather than on pointer lifetime triage.

The cost is the C++/Rust boundary. Chromium can’t pretend Rust lives in a separate universe. The browser still initializes services in C++, owns many platform abstractions in C++, and exposes C++ APIs through //base, Blink, V8, Mojo, and platform code. The early interop work therefore treated dependency direction as a design constraint: C++ called Rust, and Rust components were shaped as narrow libraries without implicit knowledge of Chromium internals. The current first-party path is broader, but the same pressure remains. Interop has to be explicit and reviewable enough that a component doesn’t become a pile of unsafe shims.

Governance is the other half. Rust code is not exempt from Chromium’s review regime. A Rust target under //components/, //third_party/, or a parser subtree still routes through the directory’s OWNERS File Governance. First-party Rust uses the rust_static_library GN template rather than the built-in rust_library, so Chromium’s compiler options and build assumptions are applied consistently. First-party Rust imports use chromium::import! from the Chromium prelude rather than assuming globally unique crate names. Third-party crates come through Chromium’s vendoring machinery and import review. Unstable Rust language and library features are unsupported by default, even though Chromium’s toolchain can technically expose them.

The decision also fits the threat model better than a language rewrite would. Chromium’s serious memory-safety risk isn’t uniformly distributed. Parser and decoder surfaces repeatedly see hostile inputs and sit close to security boundaries. Replacing selected parsers, or writing new parsers in Rust when the format enters at privilege, puts the new language where the evidence says memory safety buys the most.

Ongoing Consequences

Rust is now part of Chromium’s memory-safety program, but it is not a substitute for the rest of that program. V8 Heap Sandbox still contains V8 corruption after a JIT bug. Spanification and MiraclePtr still reduce spatial and temporal C++ bugs in existing code. Checked arithmetic and IPC validation still matter at browser-process boundaries. Rust reduces the density of selected new parser bugs; it doesn’t make parsing untrusted content safe by declaration.

A design review for a new component that parses attacker-supplied bytes can no longer assume C++ is the default language. If the component would otherwise combine untrusted input, unsafe implementation language, and privilege, the reviewer should ask why Rust, Java on Android, Swift on iOS, WebAssembly, or another memory-safe route isn’t appropriate. For cross-platform Chromium code, Rust is now the practical general answer.

Teams that own parser and decoder surfaces need Rust review capacity, Rust build knowledge, and a shared understanding of where unsafe is acceptable. Ordinary OWNERS review doesn’t automatically imply Rust expertise. A subtree that admits Rust needs reviewers who can read the Rust code, the FFI boundary, the GN target, and the surrounding C++ call site.

Rust crates don’t come from nowhere. Third-party Rust libraries live under Chromium’s vendoring and import process, and downstream products inherit the same dependency inventory when they roll the engine forward. A memory-safe parser can still carry a logic bug, a denial-of-service bug, or an unsafe block with a real memory-safety defect. The CrabbyAVIF near-miss in 2025 is the warning case: Google assigned CVE-2025-48530 to a linear buffer overflow in unsafe Rust even though the issue was caught before public release.

A coding agent trained on old Chromium examples may still default to C++ for every parser, or generate Rust that bypasses Chromium’s build and import conventions. Both are wrong. The correct proposal for a risky parser must name the memory-safe implementation path, the GN target shape, the interop boundary, the OWNERS review path, and any unsafe block’s reason for existing.

Reversal Conditions

The decision is unlikely to reverse, but it could narrow. If C++/Rust boundaries started producing enough defects, review cost, or build breakage that the memory-safety benefit disappeared, Chromium could push Rust back toward isolated third-party leaf libraries. If unstable-feature exceptions, platform support, or cross-language debugging made the toolchain too costly to keep current, the project could tighten first-party target rules. If parser and decoder replacements did not reduce memory-safety bugs enough to justify the second-language cost, future proposals would have a harder time clearing review.

That is not where the public record points today. The PNG, JSON, web-font, and CrabbyAVIF cases point to a selective path that is already part of the production tree. A broader reversal would require memory-safe C++ or a verified subset that makes Rust unnecessary for new high-risk components. Until then, Rust remains one leg of Chromium’s memory-safety strategy: new safe components where they pay off, C++ hardening where the existing code stays, and containment where bugs still get through.

Notes for Agent Context

When generating or reviewing Chromium code that parses untrusted image, font, JSON, archive, or protocol data near privilege, do not assume C++ is the default implementation language. Check whether a Rust implementation is appropriate under the Rule of 2, and state the reason if the design stays in C++.

For first-party Rust, use Chromium’s Rust build path: rust_static_library for the GN target and chromium::import! for first-party crate imports. Do not generate ad hoc Cargo-only build instructions, assume globally unique crate names, or import third-party crates outside Chromium’s vendoring process.

Treat every unsafe block as a security-review surface. Require a local safety comment that names the invariant, keep unsafe code behind a safe API where possible, and do not add an unstable Rust feature unless the Rust toolchain team has agreed to the exception.

When summarizing Rust’s security value, say that it reduces memory-safety bug density in selected components. Do not claim Rust eliminates parser risk, eliminates the need for OS process isolation, or makes downstream dependency tracking optional.

Sources

The canonical implementation policy is Chromium’s docs/rust.md, which records production-ready Rust toolchain support in M119, permits Rust anywhere in the repository subject to interop capability, requires ordinary OWNERS approval, prescribes rust_static_library for first-party libraries, and makes unstable features unsupported by default unless the Rust toolchain team agrees. The January 12, 2023 Google Online Security Blog post by Dana Jansens, “Supporting the Use of Rust in the Chromium Project,” is the public decision record for the first production Rust path: third-party Rust libraries called from C++, chosen to help satisfy the Rule of 2 without broad Rust adoption all at once. Chromium’s Memory Safety page supplies the empirical premise, including the roughly 70% memory-unsafety share of serious security bugs and the argument that process isolation alone has reached cost limits. The Rule of 2 document supplies the design constraint Rust is solving: don’t combine untrusted input, unsafe language, and high privilege.

The deployment record is in Chromium and Chrome security updates. The Chromium Security quarterly update for 2025 Q3 records Chrome 139 moving PNG parsing away from libpng to a memory-safe implementation. The November 2025 Google Online Security Blog memory-safety update states that Chromium parsers for PNG, JSON, and web fonts had been replaced with Rust implementations and then analyzes the CrabbyAVIF CVE-2025-48530 near-miss as evidence that unsafe Rust still needs review and allocator defense. The Chrome Developers web-font post records the Fontations/Skrifa path away from FreeType and its Chrome 145 Blink removal note. The older Chromium page on Rust and C++ interoperability captures the interop premise that still governs the decision: Chromium remains C++-dominated, so Rust has to fit into the C++ tree without turning every boundary into an unsafe hand-written shim.

Technical Drill-Down