Skip to content
Engineering

Patches, not black boxes: how a stealth browser is built and verified

How an anti-detect Chromium is assembled from readable patches, built reproducibly, and verified end-to-end — so you can trust the binary matches the source.

Pim
Pim· Clearcote Research
9 min read

Key takeaways

  • A fork is a stack of readable .patch files on a pinned Chromium tag — engine-level (C++/Blink) changes, not injected JavaScript.
  • Reproducible builds mean identical source yields byte-identical binaries, so anyone can verify the binary matches the published source.
  • Trust is a chain: SHA-256 (the right bytes) + signature and key fingerprint (the right author) + a reproducible build (the bytes match the source).

A stack of readable patches

A fork doesn't keep its own copy of Chromium's ~40-million-line tree. It maintains a stack of patches on top of a pinned upstream tag. In the ungoogled-chromium model, every change is a unified-diff .patch applied with patch -p1, and a plain-text patches/series file lists them in application order; patches are split into core/ (must survive every rebase) and extra/.

Two files pin exactly what you build: chromium_version.txt (the upstream tag) and a revision file for the fork's own changes. Rebasing to a new Chromium is: bump the version, re-apply the series, fix the rejects. Because every change is a readable diff, the whole modification surface is auditable — there is no opaque binary blob doing the work.

Why engine-level beats injected JavaScript

Identity changes can live in two places: compiled into the engine as C++/Blink source patches, or injected at runtime as JavaScript (the stealth-plugin approach). Projects like fingerprint-chromium take the first route — the canvas, WebGL, audio and User-Agent behaviour is patched in the render path and driven by a --fingerprint seed.

Engine-level wins for three concrete reasons. There is no JS-observable seam — the native implementation is the value, so there's no wrapper failing toString or leaving an odd property descriptor. It reaches surfaces JavaScript can't touch at all: TLS, HTTP/2 frame order, the real GPU pipeline, and worker threads. And a value patched in C++ applies uniformly across every execution context, so a worker never disagrees with the main thread. This is the same reasoning as the detection teardown.

Reproducible builds

A build is reproducible when the same source, toolchain and instructions yield bit-for-bit identical output — verified by hashing. Chromium calls this a deterministic build and enforces it on dedicated bots; the same revision must produce the same binary across machines and build directories.

Getting there means controlling the usual sources of drift: relativized paths (the output can't depend on the build-dir name), a pinned compiler (Chromium ships and version-locks its own clang rather than trusting the host), and fixed timestamps via the standardized SOURCE_DATE_EPOCH environment variable. The build is parameterized by GN args and executed by ninja; the same args are part of "same instructions".

Why it matters: reproducibility lets any independent party rebuild from published source and confirm bit-for-bit that the shipped binary contains nothing the source doesn't — a direct control against a compromised build server. Without it you must trust the builder; with it you can verify.

Verifying a release

Three checks form a chain. A SHA-256 checksum proves you have the exact bytes the project published (integrity). A signature — GPG or platform code-signing — proves who produced them (authenticity); its trust root is the signing-key fingerprint, which must be obtained out-of-band and pinned, since a signature only means "signed by this key".

The third link is the reproducible build above: it ties the bytes back to the source. Checksum plus signature still require trusting that the builder's source equals the published source; only an independent reproducible rebuild closes that gap. It's worth being blunt that contributor-submitted prebuilt binaries that aren't reproducible can't offer this last guarantee from the hash alone. Clearcote publishes per-release SHA-256 and a pinned signing-key fingerprint — see verification.

Determinism: the farbling model

For the fingerprint surfaces, the robust design is deterministic per-site noise, pioneered by Brave's "farbling". A random session token (never exposed to any page) is mixed — HMAC-SHA256 — with each first-party domain (eTLD+1) to derive a per-site, per-session seed that subtly perturbs canvas, audio and WebGL reads.

Determinism is the whole point. Fresh randomness on every read breaks legitimate uses and, worse, is itself a fingerprint: a page that reads the same canvas twice and gets different bytes knows a randomizer is active and can average many reads to recover the true value. A stable per-session value defeats that and keeps sites working — the same reason per-read randomness fails a stealth benchmark. (The idea traces to the PriVaricator and FPRandom research; it raises cost rather than being unbreakable.)

The through-line

Readable patches, reproducible builds, and a verifiable release chain aren't just hygiene — they're what let a stealth browser be trusted at all. A tool that asks you to run an opaque binary while promising it protects your identity is asking for exactly the trust it can't prove. The alternative is to make every change auditable and every build verifiable, and let anyone check. See coherence over camouflage for why the same openness applies to the identity itself.

#engineering#reproducible-builds#chromium#supply-chain

Clearcote puts this into practice

Open-source, engine-level, coherent down to the TLS handshake — a drop-in for Playwright & Puppeteer.