The Backdoor That Almost Shipped: How a Slow SSH Login Saved Linux
CVE-2024-3094 scored a perfect 10 and was days away from every stable server distribution.
On 29 March 2024 an engineer named Andres Freund posted a message to the oss-security mailing list under the subject "backdoor in upstream xz/liblzma leading to ssh server compromise". Behind that flat title was a deliberately planted backdoor in xz-utils, a compression library that sits deep in the plumbing of Linux systems and that almost no developer ever thinks about. Red Hat assigned it CVE-2024-3094.
Two releases carried it: version 5.6.0, published on 24 February 2024, and 5.6.1, published on 9 March. On machines where the compression library was pulled into the SSH server through a system dependency, the malicious code hooked the routine that validates RSA signatures during login. According to JFrog's analysis, that let an attacker holding one specific private key send payloads through SSH that were executed before the authentication step.
Not all of it was visible in the project's public git repository. The obfuscated payload was committed there on 23 February 2024, hidden inside two test files. The piece that activated it during the build lived elsewhere: Freund found the offending line in a script called build-to-host.m4 that is not part of that script's upstream source and is not used by xz in git, but is present in the tarballs released upstream — the archives distributions actually download and compile. On 15 February 2024, nine days before the first bad release, the same account had added an ignore rule for that file to the repository.
Caught by half a second
Freund did not find this by auditing anything. He had noticed odd symptoms around liblzma on Debian sid installations over the previous weeks: SSH logins using a lot of CPU, plus valgrind errors. So he measured it. A login attempt as a non-existent user took roughly 0.299 seconds on one system and roughly 0.807 seconds on the backdoored one — about half a second of work nobody could account for. The login still failed with an ordinary permission-denied message. Only the timing gave it away.
That is the uncomfortable part, because the campaign behind it was patient. JFrog's timeline dates the first commit from the account that later planted the code, operating under the name "Jia Tan", to 6 February 2022. On 30 November 2022 the original maintainer, Lasse Collin, added that account to the project's bug-reporting alias. On 18 March 2023 the account built and released xz 5.4.2 on its own. In late June and early July 2023 came the groundwork: an IFUNC implementation later abused to hook into the SSH server, and a pull request that switched off IFUNC fuzzing in oss-fuzz. The obfuscated payload arrived on 23 February 2024, two years after that first commit. Freund's own reading was blunt: given activity over several weeks, the committer was either directly involved or their system had been severely compromised, and he considered the second explanation the less likely one.
Timing was the one thing that went wrong for the attacker. Freund noted that 5.6.0 and 5.6.1 had not yet been widely integrated by Linux distributions, and where they had, mostly in pre-release versions. JFrog's breakdown matches: the releases reached Fedora 40 and Rawhide, Debian testing and unstable, Arch, openSUSE Tumbleweed, Kali and Alpine Edge, while Red Hat Enterprise Linux, Ubuntu, Amazon Linux and Gentoo were not affected. The versions that run most production servers had not picked it up.
What this means if you are building something
Nobody chose to install this. It arrived as a dependency of a dependency, inside a library that never appears in a project plan.
Know what is actually in your build. Not the packages someone listed, but the full transitive set underneath them. Producing that inventory is a task with a real cost, and it belongs in a budget once, calmly, rather than in the middle of an incident.
Pin versions and update deliberately. A build that resolves "latest" at deploy time will pull in a compromised release the day it appears. A pinned version with a scheduled review gives you a window in which somebody else finds the problem first — which is roughly what happened here.
Ask who maintains the things you depend on. xz had one original maintainer, Lasse Collin. Within about thirteen months of the new contributor's first commit, that account was on the project's bug-reporting alias and cutting releases. This is not a criticism of Collin; spotting a helpful-looking contributor playing a two-year game is genuinely hard. But when a small, load-bearing dependency changes hands, treat it as information worth noticing.
Be able to answer "are we affected?" within the hour. The value of an inventory is not the document. It is that when an advisory lands on a Friday afternoon, somebody can say which of your servers run the affected version and which do not, without logging into each one to check.
Freund's own recommendation was to upgrade any potentially vulnerable system as soon as possible. The broader lesson is duller and more useful: the dependencies nobody thinks about are precisely the ones an attacker was willing to spend two years on.