--- slug: untrusted-renderer-axiom type: concept summary: "The foundational posture that the browser process must treat every message from a renderer as potentially attacker-controlled, regardless of any validation the renderer claims to have performed." created: 2026-05-12 updated: 2026-05-13 last_link_verified: 2026-05-13 related: browser-renderer-split: relation: refines note: "The browser-renderer privilege split is the structural asymmetry; the untrusted-renderer axiom is its operational form, which binds every browser-side handler to validate as if the renderer were attacker-controlled." multi-process-architecture: relation: builds-on note: "The OS-enforced process boundary established in 2008 is what makes the axiom tractable: there is exactly one validation choke point, on the browser side, rather than scattered defensive checks across an in-process attack surface." site-isolation: relation: extended-by note: "Site Isolation propagates the axiom across cross-site iframes so each cross-site frame's renderer is treated as a separate, separately-hostile origin rather than one whose sibling's claims can be trusted." stateless-ipc-interface: relation: governs note: "The Stateless IPC Interface pattern is the direct corollary: every Mojo method has to validate the full message in one call because the axiom forbids carrying validated state across renderer calls." stateful-ipc-init: relation: violated-by note: "Stateful IPC Initialization is the antipattern the axiom most directly forbids: presuming validation done on an earlier Init() call across a hostile boundary." ipc-integer-discipline: relation: enforces note: "The IPC Integer Type Discipline is the type-level enforcement of the axiom for the most common renderer-supplied input — count fields, offsets, and sizes — which a compromised renderer can set to attacker-chosen values." escape-chain: relation: motivates note: "The sandbox-escape chain's middle link is a Mojo handler that trusted a renderer claim; removing the trust is what the axiom is for." three-lgtm-gate: relation: enforced-by note: "The three-LGTM API owner gate is the governance mechanism that catches new browser-side interfaces that omit input validation; the axiom is the rule the reviewers apply." --- # Untrusted Renderer Axiom *The foundational security posture that the browser process must treat every message from a renderer as potentially attacker-controlled, regardless of any validation the renderer claims to have performed.* > **Concept** > > Vocabulary that names a phenomenon. > "Code running in the renderer process should be assumed to be running on behalf of an attacker." > — Chromium project, `docs/security/rule-of-2.md` ## What It Is The axiom is a single rule the Chromium project applies to every code path that crosses from a renderer process into the privileged browser process: the renderer is hostile, every byte it sends is attacker-chosen, and any browser-side code that reads the message must validate as if no validation ran upstream. The rule is not heuristic. Reviewers, the `docs/security/rule-of-2.md` document, and the API-owner gate treat it as a hard architectural invariant. A Mojo handler that omits an input check on the grounds that the renderer already checked is rejected at review even when the renderer's check happens to be correct. The reasoning rests on the [*Multi-Process Architecture*](multi-process-architecture.md) substrate and the [*Browser-Renderer Privilege Split*](browser-renderer-split.md) it produced. A renderer parses web content drawn from the open web: HTML, CSS, JavaScript, image bytes, font glyphs, video streams. Any of those inputs can carry a memory-corruption primitive against the renderer's parsers; image decoders, font shapers, and JavaScript JIT compilers are large, written in C++, and historically the source of regular vulnerabilities. The threat model treats renderer compromise as a constantly available outcome for a motivated attacker. The consequence follows: any code that runs in a privileged process and reads a renderer message has to behave as if the message arrived from a process the attacker controls, because at any given moment some renderer somewhere is in that state. The axiom's name is the project's own. The Chromium security team uses the phrase "the renderer is untrusted" in design reviews; `rule-of-2.md` states the principle directly; the threat-model section of `docs/security/` returns to it as the foundational assumption. *Chromium Patterns* takes the name as canonical and the rule as binding. The axiom holds *even when the renderer's own validation logic is provably correct*. A correct check inside an untrusted process is not the same fact as a correct check inside a trusted process. The renderer's code can be exactly right at compile time; that same code is exactly what an attacker can replace via a memory-corruption primitive once the renderer is compromised, and the attacker can do so before the message is sent. Trust in a message comes from where the *next* check runs, not from where the *first* check ran. ## Why It Matters Naming the axiom converts a structural asymmetry into an enforceable rule. The privilege split tells a contributor that the renderer is unprivileged and the browser is privileged. It doesn't tell the contributor whether a renderer claim ("this URL is same-origin," "this iframe is allowed to access that storage key," "this `uint32_t` count fits in the buffer") can be relied on. Without the axiom, a reasonable engineer reads the asymmetry and concludes that the renderer is a *less-privileged peer* whose claims are inputs to a cooperative protocol. With the axiom, the same engineer reads the same asymmetry and concludes that the renderer is a *hostile peer* whose claims are exploitation primitives waiting for a credulous handler. The asymmetry alone is ambiguous; the rule resolves it. The axiom also makes "double validation" coherent rather than redundant. Reviewers and new contributors regularly notice that a Mojo interface validates inputs on both sides (the renderer rejects malformed messages before sending; the browser rejects them again before acting), and ask whether one of the checks is wasted work. The axiom answers: the renderer's check is for the user's benefit (it catches benign mistakes from the page's JavaScript and produces useful error messages); the browser's check is for the user's safety (it stops the message even when the renderer has been replaced by an attacker). The two checks defend against different threats and neither is redundant. The Chrome Security blog has said this directly in its discussions of the Rule of 2; `docs/security/mojo.md` documents the rule as binding for Mojo interface authors. For governance, the axiom gives the [*Three-LGTM API Owner Gate*](three-lgtm-gate.md) something concrete to enforce. A new Mojo interface arrives at API-owner review; the reviewers ask, for each method, what an attacker-controlled renderer can do by varying the inputs. The axiom is the lens, and the answer determines whether the interface ships. A feature whose security depends on the renderer behaving correctly is asking the API owners to suspend the axiom for its sake, and the gate refuses. For exploit response, the axiom is what makes the [*Sandbox Escape Chain*](escape-chain.md) parse cleanly. The chain's middle link is almost always a browser-side handler that trusted something the renderer told it. A bounty report that names such a handler is processed against the axiom as the rule violated, and severity rises when the violation is direct. For downstream vendors building Chromium-based products (Microsoft Edge, Brave, Opera, Vivaldi, Electron applications, WebView2 embedders), the axiom is inherited along with the upstream code. Custom browser-side handlers that downstream vendors add (for telemetry, enterprise policy, or custom protocols) have to respect the axiom or they introduce attack surface the upstream project doesn't have. CVE history shows several downstream incidents in which a vendor's custom IPC handler skipped a validation the upstream pattern would have required; the axiom is the rule the vendor's review process needed and didn't run. For AI coding agents working in Chromium and Chromium-derived code, the axiom is among the load-bearing facts to load into context. An agent that holds it produces Mojo handlers that validate every input on the browser side, and refuses to propose shortcuts that lean on the renderer's claims. An agent that doesn't holds neither, and produces architecturally invalid code that compiles, passes renderer-side tests, and is rejected at security review every time. ## How to Recognize It The axiom shows up at several recognizable points in the codebase, the documentation, and the review record. In the source tree, every Mojo interface implementation hosted in `content/browser/` reads as if the calling renderer were attacker-controlled. URL parameters pass through `GURL` and `url::Origin` parsers that check well-formedness rather than reading fields out of the message. Origin claims are cross-checked against the renderer's `SiteInstance` identity (the browser process knows which site each renderer is hosting, from the [*Site Isolation*](site-isolation.md) machinery) rather than against an `origin` field in the message. Integer count and offset fields are validated through `base/numerics/safe_conversions.h` and the `CheckedNumeric<>` family before they index into buffers. The pattern is so consistent that the absence of these checks in a new browser-side handler is the most reliable signal a reviewer has of a security gap. In the documentation, `docs/security/rule-of-2.md`, `docs/security/mojo.md`, and the threat-model section of `docs/security/` name the axiom explicitly. The Rule of 2 (any feature parsing untrusted input may pick at most two of {written in C++, runs in the browser process, parses untrusted input}) is the heuristic operational form: when a feature would be the disallowed combination, the project pushes the parsing into a sandboxed utility process or refuses the design. The Rule of 2 is the easy first check a reviewer applies; the axiom is what the Rule of 2 is for. In review threads on Gerrit and on chromium-review.googlesource.com, the axiom surfaces as one of a small set of standing comments. "This handler needs to validate the origin against the `SiteInstance`, not against the message field." "This `size` value has to be checked before the indexed read." "This URL needs to be parsed through `GURL`, not read as a string." Each is a particular consequence of the general rule, and a contributor reading a sample of past reviews sees them recur until the underlying axiom becomes obvious. In incident reports, the axiom is the most-cited principle when a vulnerability is rooted in IPC handling. Project Zero's writeups of historical Chromium sandbox escapes routinely conclude with a description of which browser-side check was missing; the Chrome Security blog's post-mortems follow the same form. The axiom is the rule the report names as violated. ## How It Plays Out Three concrete scenarios illustrate the axiom in operation. A team adds a new Mojo interface that lets a renderer request thumbnail rendering for a list of URLs in the user's history. The naive draft accepts a `repeated string urls` field on the message, hands the list to the thumbnail service, and returns the bytes. API-owner review rejects the draft on the axiom: a renderer is allowed to ask for thumbnails of URLs its session can reach, not arbitrary URLs, and the browser must check the request against the user's actual history rather than against the renderer's claim. The revised interface parses each URL through `GURL`, checks each against the user's history records held in the browser process, and returns thumbnails only for matches. The renderer's earlier check on the URL list still runs (it filters typo'd entries before the IPC fires), but the browser-side check is the load-bearing one for the user's security. A contributor encounters an existing Mojo interface with a method that takes a `uint32_t count` and treats it as the length of a renderer-supplied array of color stops. The count is used directly as a buffer index in the browser-side rendering path, and the contributor files a security bug. Triage classifies it as High severity on the axiom: a compromised renderer can set `count` larger than the array, the browser-side index overruns the buffer, and the bug is exploitable. The fix wraps the index through `base::CheckedNumeric`. The [*IPC Integer Type Discipline*](ipc-integer-discipline.md) pattern is updated with the incident as an exhibit. A downstream-vendor security team audits a custom IPC handler the vendor added to expose enterprise-policy state to renderer-resident code. The handler reads a string from the renderer and uses it as a key into the vendor's policy database. The audit applies the axiom and finds two missing checks: the renderer's `SiteInstance` is never consulted, so any site can request any policy key; and the key is not validated for shape, so an attacker-supplied key can traverse the database's internal structure. The vendor patches both, and files the post-mortem with the upstream `docs/security/` team as an example of why downstream vendors need a security-review process that applies the axiom as rigorously as upstream's. ## Consequences Holding the axiom buys several operational properties for the project. Security review concentrates where it pays off. Code under `content/browser/` that reads renderer input is read with the axiom in hand; code under `content/renderer/` is read against a different threat model (renderer-internal correctness, not browser-process safety). Scarce reviewer attention follows where the axiom places it. Mojo interface design defaults to stateless single-call methods rather than multi-call protocols. The [*Stateless IPC Interface*](stateless-ipc-interface.md) pattern makes the axiom enforceable in practice: a method whose validation runs entirely on the one message it received is auditable against the axiom; a method that presumes state from a prior call isn't. The [*Stateful IPC Initialization*](stateful-ipc-init.md) antipattern is what happens when the convenience of carrying state across calls beats the axiom in design review. Downstream Chromium-based products inherit the rule. When a vendor's custom IPC handler ships without a security review that applies the axiom, the resulting CVE is the vendor's; when the vendor's review applies the axiom rigorously, the upstream invariant holds across the integration. The cost of the axiom is paid at the integration boundary; the benefit accrues to the user. There are real engineering costs. Validating every input on the browser side is more code, slower to write, and slower to execute than trusting the renderer. The Rule of 2's prohibition on C++ parsing of untrusted input in the browser process forces a sandboxed-utility-process design for some features (image decoding, font shaping, video parsing), and the IPC cost is paid every time the parser runs. The project pays these costs deliberately; the axiom is the rule that says they're worth paying. ## Notes for Agent Context Treat every input from a renderer process as attacker-controlled, with no exceptions. Inside any browser-side Mojo handler, validate every `uint32_t` count, offset, and size through `base/numerics/safe_conversions.h` (`CheckedNumeric`, `base::CheckMul`, `base::CheckAdd`) before using it as a buffer index; parse every URL through `GURL` and read its components through `url::Origin`; and cross-check every origin claim against the renderer's `SiteInstance` identity (`RenderFrameHost::GetSiteInstance()->GetSiteInfo()`), never against fields the renderer included in the message body. Never propose a browser-side handler that omits a check on the grounds that the renderer already validated the input; renderer validation doesn't survive a renderer compromise and is never the load-bearing check. Draft every new Mojo method as a stateless single-call method that validates everything it needs from the one message it receives; refuse to chain it onto state from a prior `Init()` call. ## Sources The canonical primary source is the Chromium project's `docs/security/rule-of-2.md`, which states the principle directly in its opening paragraph and uses it as the premise for the Rule of 2 heuristic the rest of the page formalizes. `docs/security/mojo.md` is the operational extension to Mojo interface authors, naming the validation requirements every browser-side method has to meet. The threat-model section of `docs/security/` (`docs/security/side-channel-threat-model.md` and surrounding pages) is the design-level statement of why the renderer is treated as hostile by default. The Chrome Security blog, in its public discussions of the Rule of 2 and of historical sandbox escapes, names the axiom as the underlying principle and walks the consequences for downstream vendors. Project Zero's analyses of past Chromium sandbox escapes (Ned Williamson's writeups on IPC bugs, the V8 escape chains documented by other team members) consistently identify a missing browser-side check as the proximate cause; the implicit reference is to the axiom every time. ## Technical Drill-Down - [`docs/security/rule-of-2.md`](https://chromium.googlesource.com/chromium/src/+/main/docs/security/rule-of-2.md) — the project's canonical statement of the axiom and the Rule of 2 heuristic that follows from it; short, binding, and the entry point for new contributors. - [`docs/security/mojo.md`](https://chromium.googlesource.com/chromium/src/+/main/docs/security/mojo.md) — the operational extension for Mojo interface authors; lists the validation idioms (`base::CheckedNumeric`, `url::Origin`, `SiteInstance` identity) that the axiom requires. - [`base/numerics/safe_conversions.h`](https://chromium.googlesource.com/chromium/src/+/main/base/numerics/safe_conversions.h) — the project's checked-arithmetic library; every `uint32_t` count from a renderer is validated through this header before it indexes into a buffer. - [`content/browser/site_instance_impl.cc`](https://chromium.googlesource.com/chromium/src/+/main/content/browser/site_instance_impl.cc) — the implementation of the `SiteInstance` identity used to cross-check renderer origin claims; the browser-side ground truth that the axiom directs handlers to consult. - [*The Chrome Security Team Discusses How to Stay Secure*, Chrome Security blog](https://security.googleblog.com/) — the public-facing series in which the Rule of 2, the axiom, and the post-mortems of historical sandbox escapes are explained for an outside audience. - [Project Zero blog, Chromium sandbox-escape writeups](https://googleprojectzero.blogspot.com/) — recurring detailed analyses of past escapes; the missing browser-side check is the proximate cause in nearly every case. --- - [Next: Stateful IPC Initialization](stateful-ipc-init.md) - [Previous: Sandbox Escape Chain](escape-chain.md)