A single tampered copy of GNU strip, placed in the NixOS binary seed, was enough to backdoor almost every binary in a complete graphical installer. The installer built from a real nixpkgs revision with no failures, and the payload rode from one generation of strip to the next until it reached the final standard environment, after the seed itself had already dropped out of the dependency closure.
That result comes from "Trusting-Trust Attack against an Entire Linux Distribution through Binary Manipulation," a paper by Julien Malka posted to arXiv in July 2026 and revised in September. The choice of tool is what makes it worth reading.
Ken Thompson's trusting-trust attack, from his 1984 Turing Award lecture, put the backdoor in a compiler. A compromised compiler recognises when it is building a sensitive target and inserts a backdoor, and recognises when it is compiling itself and reinserts the backdoor-insertion logic, so the trick survives a clean rebuild from clean source. The source stays honest and the binary does not. For four decades the attack has been filed under "compilers are special," on the reasoning that a compiler is the one tool that reads your source and emits your binary, giving it both the opportunity and a natural place to hide the self-reproduction.
GNU strip has neither property. It does not read source code and it does not generate any. It takes a finished ELF file and removes symbol tables and debugging information to make the binary smaller. Malka builds the whole attack out of manipulations of finished ELF files, with strip as the carrier, which is enough to reproduce the Thompson result without ever touching a line of source.
NixOS makes a clean target because its bootstrap is explicit about what it trusts. Nix builds the distribution from a small binary seed, uses that seed to build the real toolchain, rebuilds, and discards the seed, so the final packages ideally depend only on things built from audited source. strip sits in that seed. Once the tampered strip is there, it processes the binaries produced during the bootstrap, including the next strip, and carries its payload forward at each stage. By the time the seed leaves the closure the backdoor is already in the standard environment, so the shipped packages carry it even though nothing from the seed remains in their dependency graph.
The part worth sitting with is what this does to reproducible builds. A reproducible build proves that the published source and build inputs yield the published binary, bit for bit, and that independent rebuilders all get the same result. If one of those build inputs is a poisoned strip in the seed, every independent rebuilder reproduces the same backdoored binary and confirms the hash. Reproducibility establishes that rebuilders agree on the output. It says nothing about whether the inputs were clean.
So the trusted computing base of a build is larger than the compiler. It is every executable in the bootstrap seed. strip neither reads nor writes source, yet it carried the payload just by rewriting finished binaries on their way to becoming later stages. Any seed tool that handles those binaries sits in the same position once an attack no longer needs to touch source. Audit effort pointed at the compiler walks straight past the rest of the seed.
That moves the audit target from the compiler to the whole seed. A smaller seed gives a payload fewer binaries to hide in. Matching rebuilds only show that everyone used the same inputs, not that the inputs were clean, so the seed binaries themselves are what have to be checked.
Top comments (0)