On March 29, 2024, Red Hat disclosed CVE-2024-3094, a CVSS v3.1 score of 10.0 — the maximum possible — assigned to a backdoor embedded in xz Utils versions 5.6.0 and 5.6.1. The malicious code, classified under CWE-506 (Embedded Malicious Code), modified specific functions in liblzma so that any software dynamically linked against it, including sshd on glibc-based Linux systems via a systemd dependency chain, could have its behavior intercepted and manipulated by a remote attacker holding a specific private key. It was found not by a security scanner but by a single engineer, Andres Freund, who noticed SSH logins on a Debian sid box taking roughly half a second longer than expected and consuming unexplained CPU. The backdoor's insertion was the payoff of a social-engineering campaign that started years earlier under the name "Jia Tan," who spent over two years contributing legitimate patches to xz before being handed co-maintainer access. This post walks through how the persona operated, how the build-time trigger actually worked, and what concrete detection lessons it leaves for maintainers of any open-source project.
Who was "Jia Tan" and how did the trust-building campaign work?
The GitHub account JiaT75 was created on January 26, 2021, and made its first xz Utils contribution — a minor .editorconfig patch — on October 29, 2021. Over the following year, Jia Tan submitted legitimate code, translations, and CI maintenance, while separate accounts (including one using the name "Jigar Kumar") pressured original maintainer Lasse Collin on the xz-devel mailing list through 2022, complaining about slow releases and pushing him to add a co-maintainer. Kaspersky's Securelist team, which published a two-part technical breakdown of the incident, documented this as a coordinated pressure campaign rather than organic community friction. Jia Tan created the official XZ Utils GitHub organization on December 12, 2022, and shipped their first release as maintainer the next day. Of the roughly 500-plus commits attributed to the persona across projects, researchers found only a handful were directly malicious — the rest were real engineering work, sustained for over two years, that existed solely to make the eventual backdoor commits look routine.
How did the malicious code get into the build without appearing in the source review?
The backdoor was not visible in the human-reviewable .c source files at all. According to the widely cited technical timeline compiled by Sam James (a Gentoo xz co-maintainer) and independent analyses from Kaspersky and StepSecurity, the attacker modified build-to-host.m4, a file in xz's autotools build chain, to extract a hidden payload from a test file named bad-3-corrupt_lzma2.xz, which was checked into the repository disguised as a corrupt-input test fixture for the test suite. During ./configure and make, that file was decoded with a chain of sed and tr transformations designed to evade casual grep-based auditing, then used to extract and link a second hidden object drawn from another test file, good-large_compressed.lzma. The result was a prebuilt object file — never compiled from visible source — spliced into liblzma only when built as an RPM or DEB package on x86-64 Linux with glibc, GCC, and the GNU linker.
What did the backdoor actually do once it was running?
Once linked into liblzma, the payload used IFUNC resolvers — a legitimate glibc mechanism (crc32_resolve, crc64_resolve) that lets a binary pick an optimized function implementation at load time — introduced by Jia Tan through ordinary-looking commits back in June 2023. The attacker repurposed IFUNC resolution to hook RSA_public_decrypt inside OpenSSH's authentication path, since Debian- and RPM-based distributions commonly link sshd against liblzma through systemd's libsystemd dependency for compression support. NVD's own summary describes the result as "a modified liblzma library that can be used by any software linked against this library, intercepting and modifying the data interaction with this library," and CISA's March 29, 2024 alert and the GitHub Security Advisory GHSA-rxwq-x6h5-x525 both warned of unauthorized SSH access as the primary risk. Because the hook activated only under a specific build configuration and reportedly checked for a hardcoded attacker key before altering authentication behavior, ordinary SSH traffic on unaffected systems saw no change at all.
How was it actually caught, and why did static analysis miss it?
It was caught by a performance anomaly, not a security tool. Andres Freund, a PostgreSQL contributor working for Microsoft, was benchmarking Postgres and noticed SSH logging in about 0.5 seconds slower than expected, alongside stray Valgrind errors, on Debian's unstable branch running xz 5.6.1. He traced the delay to liblzma and, within days, had reverse-engineered enough to post full disclosure to the oss-security mailing list on March 29, 2024. No SAST rule, SCA scanner, or CVE database flagged it beforehand, because the malicious payload existed only as a binary blob assembled at build time from files that looked like test fixtures — there was no vulnerable source pattern to lexically match. This is precisely the class of risk Safeguard's own deep dependency scanning documentation flags: alongside SolarWinds' SUNBURST, xz Utils is cited as an example of compromise sitting several dependency levels deep, in build tooling and transitive links most SCA tools scanning to depth 50-60 never reach, versus the depth-100 traversal needed to even see the affected node.
What should open-source maintainers actually change because of this incident?
Concretely: audit configure.ac/m4 build scripts with the same scrutiny as application code, since this backdoor lived entirely in autotools glue and test-fixture files that normal code review skipped. Require more than one maintainer's sign-off before granting release/publish rights to a new co-maintainer, regardless of how many legitimate patches they've submitted — Lasse Collin's own public statements after disclosure noted the multi-year patience of the pressure campaign was specifically designed to exploit maintainer burnout. Treat unexplained latency or resource-usage regressions in security-critical paths (SSH, TLS, auth) as an investigation trigger, not noise, since that's the only signal that actually surfaced this attack. Pin and reproducibly build release tarballs separately from the git source tree, since the xz backdoor was present in the distributed tarball via the modified build-to-host.m4 but not fully visible in the GitHub repository diff view most reviewers checked.
How Safeguard Helps
Safeguard's deep dependency scanning walks the full resolved dependency graph to depth 100 — roughly 40 levels past the 50-60 depth ceiling common in SCA tools like Snyk or Dependabot's direct-plus-one-level model — specifically so that a compromise buried in a transitive build dependency, the same shape as xz Utils and SolarWinds SUNBURST, doesn't fall outside scan coverage. Every resolved package is cross-referenced against known typosquat patterns and internal versus public registry provenance to catch dependency-confusion attempts before they ship, and Safeguard generates a CycloneDX SBOM on every build so that when the next build-time backdoor is disclosed, teams can query "are we affected, and where" against a live inventory instead of re-auditing configure.ac files from scratch across every repository they maintain.