[Analysis]
xz-utils backdoor (CVE-2024-3094): a malicious maintainer in a core Linux library
Two years of patient social engineering put a backdoor into a compression library at the heart of Linux. It was caught by accident, because SSH logins got half a second slower. What it teaches anyone who reviews code or depends on open source.
On 29 March 2024, Andres Freund, a PostgreSQL developer, posted to the
oss-security mailing list about something odd. SSH logins on a test machine were
using more CPU than they should and taking around half a second longer. He
traced the delay to liblzma, part of the xz compression tools that almost
every Linux distribution ships. What he’d found was a deliberately planted
backdoor in xz versions 5.6.0 and 5.6.1, since tracked as CVE-2024-3094 with the
maximum severity score of 10.0.
It had been caught mostly in development and rolling-release distributions, before it reached the stable releases that most servers run. That was luck, not design, and it has become the case study we reach for when people ask what code review is for.
Two years of patience
The code wasn’t the clever part. The trust was.
From 2021, someone using the name “Jia Tan” began contributing useful patches to xz. Through 2022, other accounts, widely believed to be sock puppets, piled pressure on the project’s long-standing, unpaid maintainer, complaining about slow progress and pushing for a new co-maintainer. Jia Tan was that person, and in time was making releases of xz themselves.
The backdoor itself was split so that no single change looked alarming:
- The payload was hidden in binary “test files”: the kind of opaque blob that reviewers routinely skip because there’s nothing to read.
- The trigger was only in the release tarballs. A modified build macro that extracted and compiled the payload was in the downloadable release, not in the project’s Git repository. Anyone reviewing the source on GitHub was reviewing something subtly different from what distributions actually built.
[Two years to build trust]
- 2021First helpful patches arrive
- 2022Sock-puppet accounts press a tired maintainer; "Jia Tan" becomes co-maintainer
- Feb 20245.6.0 and 5.6.1 ship a backdoor, hidden in the release tarballs
- 29 Mar 2024Slow SSH logins lead to its discovery
CVE-2024-3094, CVSS 10.0
What this means for code review
Most of us will never face an attacker this patient. The lessons still apply to ordinary projects:
- Review what you ship, not just what’s in the repository. If your build pulls in a release artefact, a container image or a vendored copy, that’s the code that runs. Build from source you can see where you can, and treat any difference between the two as a finding.
- Opaque files in a diff are a finding in themselves. Binary fixtures, minified bundles and generated code deserve a question: where did this come from, and how would we know if it changed?
- Build scripts are code. Makefiles, CI workflows,
package.jsonscripts and macros run with the same privileges as everything else, and they rarely get the same scrutiny. Review them as carefully as the application. - Anomalies are signals. The backdoor was found because someone refused to shrug off half a second of latency. Performance regressions, unexpected network calls and new dependencies in a pull request are all worth a “why?”.
- Know which of your dependencies rest on one person. A large amount of critical software is maintained by one or two volunteers. That isn’t a reason to avoid it, but it is a risk to know about, and a good reason to support the projects you rely on.
Protecting the build, not just the code
The backdoor never appeared in a diff anyone was asked to approve. It went in through the release tarball and the build scripts, and that’s where we’d put the effort first:
- Control who can change the repository and cut a release. Protect the main branch, require review before merging, and keep a short, known list of people who can publish a release, each of them using MFA.
- Make releases reproducible from source. If anyone can rebuild what you ship from the tagged source and get the same result, a tarball with extra files in it stands out. If they can’t, everyone is trusting whoever built it.
- Treat the pipeline like production. CI runners, build secrets and deployment credentials need the same access control and monitoring as your live systems, because whoever can change them can change what you ship.
- Log changes to the build itself, so that when something odd turns up, you can find out when it changed and who changed it.
None of this is new. Two of the eight principles in the NCSC’s secure development and deployment guidance, protecting the code repository and securing the build and deployment pipeline, cover the same ground. The government’s voluntary Software Security Code of Practice (May 2025) makes build environment security one of its four themes. If you sell software to other organisations, expect them to start asking how you handle it.
Sources
- Andres Freund, backdoor in upstream xz/liblzma leading to ssh server compromise, oss-security (29 March 2024)
- CISA, Reported supply chain compromise affecting XZ Utils data compression library, CVE-2024-3094 (March 2024)
- NCSC, Secure development and deployment guidance
- DSIT and NCSC, Software Security Code of Practice (May 2025)