ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
Topics
sre111localhost lab102performance70python58javascript47bundle size36benchmarking35node.js35web development21typescript19benchmark16content creation15All topics
About
Loading article…

ShopperCove

Hands-on notes on developer tools, written after the tool has actually been run.

All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove

On this page

  1. Summary
  2. Timeline
  3. Root cause
  4. Impact
  5. What went well
  6. Action items
  7. FAQ
  8. Which xz versions had the backdoor?
  9. How was the xz backdoor discovered?
  10. Why could the xz backdoor reach sshd?
  1. Blog

XZ Utils Backdoor: A Technical Deep Dive

How a two-year-long social engineering effort inserted a backdoor into xz/liblzma's release tarballs, and how a Postgres developer's curiosity about slow SSH logins caught it.

10 September 2026·7 min read

Summary

Disclosure

This post contains affiliate links. If you buy through them, I may earn a commission at no extra cost to you. I only make firsthand claims about products I have actually used.

On this page
  1. Summary
  2. Timeline
  3. Root cause
  4. Impact
  5. What went well
  6. Action items
  7. FAQ
  8. Which xz versions had the backdoor?
  9. How was the xz backdoor discovered?
  10. Why could the xz backdoor reach sshd?

Summary

The XZ Utils backdoor was malicious code in the release tarballs of xz/liblzma 5.6.0 and 5.6.1, hidden in test files and a modified build-to-host.m4 that does not exist in the git repository, and on affected systems it could compromise the OpenSSH server through libsystemd's dependency on liblzma. Andres Freund disclosed it on oss-security on 29 March 2024 after noticing slow, CPU-heavy SSH logins on Debian sid, before the affected versions reached stable distributions.

Timeline

  • Prior weeks (undated in sources): Freund notices SSH logins on Debian sid taking excessive CPU and producing valgrind errors while doing unrelated Postgres benchmarking work (openwall.com).
  • Prior ~2 years: A contributor using the handle "Jia Tan" (GitHub account JiaT75) is active in the xz project, including adding binary test files later found to contain obfuscated exploit payloads (news.ycombinator.com).
  • Before release: The same account pushes a Fedora packager to add xz 5.6.x to Fedora 40 and 41, citing "great new features," and helps fix a valgrind issue that, per the packager's account, was actually caused by the backdoor itself (news.ycombinator.com).
  • 5.6.1 release: Further commits work around the valgrind/crash symptoms caused by the injected code, adjusting the exploit accordingly (openwall.com).
  • Night before disclosure: The Fedora packager describes "an inadvertent break of the embargo," triggering an overnight race to fix the issue before public disclosure (news.ycombinator.com).
  • Fri, 29 Mar 2024, 08:51:26 -0700: Freund publishes a full technical writeup to oss-security: the compromised tarball, the compromised test files, affected systems, and reproduction steps (openwall.com).
  • Same day: GitHub suspends the JiaT75 and Lasse Collin (Larhzu) accounts and disables all Tukaani project repositories, including the releases page (news.ycombinator.com).
  • Shortly after disclosure: Alpine Linux ships a patch removing the affected code (news.ycombinator.com).
  • Following disclosure: Maintainers begin auditing and removing Jia Tan's public key from keyrings and approved-publisher lists across Arch, openSUSE, and AUR packages (pacman-static, mingw-w64-xz) (news.ycombinator.com).

The sources give no specific time for "full recovery" beyond these individual patches and account suspensions.

Root cause

The proximate cause was malicious code injected into the release tarballs of xz 5.6.0 and 5.6.1 — a line added to m4/build-to-host.m4 that does not exist in the upstream git repository (openwall.com). That line runs an obfuscated script at the end of configure, which, under matching preconditions, patches liblzma's Makefile to pipe test data through sed, tr, and xz -d into /bin/bash, deobfuscating and executing the real payload. The payload was hidden as binary blobs inside two test files, tests/files/bad-3-corrupt_lzma2.xz and tests/files/good-large_compressed.lzma — files not actually exercised by any real test in 5.6.0 (openwall.com).

Contributing factors:

  • Tarball/repo divergence as accepted practice. Autoconf-based C projects commonly ship generated files (like configure and build-to-host.m4) in release tarballs that don't appear in git — normal for build tooling, but it also gave the attacker a hiding place invisible to anyone auditing the public repo (news.ycombinator.com).
  • Long-term trust-building. The account had been an active xz contributor for roughly two years, doing routine work like adding test files, which normalized binary blobs in the repo (news.ycombinator.com).
  • Social engineering of downstream maintainers. The account pushed directly for inclusion in Fedora 40/41, framed the release as having valuable new features, and helped fix bugs the backdoor itself had introduced — building credibility and urgency (news.ycombinator.com).
  • Anti-analysis conditions. The payload activated only under narrow conditions — x86-64 Linux, glibc, gcc, GNU linker, and specifically Debian- or RPM-style package builds — designed, per Freund's analysis, to make reproduction harder for investigators (openwall.com).
  • A separately sabotaged sandbox check. A commit attributed to the same contributor introduced a stray character into C code responsible for a Landlock sandboxing capability check, silently disabling that check — a second, independent weakening of defenses flagged by commenters reviewing the commit history (news.ycombinator.com).

Impact

  • Observed slowdown: Freund's writeup reports SSH authentication attempts against localhost taking roughly 2.7x longer with the backdoored liblzma present:
before:
real    0m0.299s
user    0m0.202s
sys     0m0.006s

after:
real    0m0.807s
user    0m0.202s
sys     0m0.006s

(openwall.com)

  • Affected package state: Debian sid installations were confirmed affected; xz 5.6.0/5.6.1 had not yet been widely integrated by distributions, and where present, mostly in pre-release branches (openwall.com).
  • Near-miss for stable distros: The backdoor was in the process of being pushed into Fedora 40 and 41 via direct engagement with a packager (news.ycombinator.com).
  • Mechanism of exposure: OpenSSH does not link liblzma directly, but several distributions patch OpenSSH for systemd notification support, and libsystemd depends on liblzma — this indirect chain is what exposed sshd (openwall.com).
  • Downstream cleanup surface: The contributor's public key also appeared in AUR packages (mingw-w64-xz, pacman-static) and in openSUSE and Arch keyrings/publisher lists, prompting maintainers to review and remove those references (news.ycombinator.com).

The sources give no count of affected end users, servers, or organizations.

What went well

  • Anomaly-driven detection. Freund wasn't looking for a backdoor — he noticed unrelated performance anomalies during other work and traced them to the injected code (openwall.com).
  • Documented reproduction. The writeup lists exact trigger preconditions (unset TERM, argv[0] of /usr/sbin/sshd, unset LD_DEBUG/LD_PROFILE, set LANG) and a reproduction command:
env -i LANG=en_US.UTF-8 /usr/sbin/sshd -D

(openwall.com)

  • Disclosure included commit hashes, file paths, and tooling. The oss-security post gave exact commit hashes, injected code excerpts, and the analysis toolchain (perf record, gdb), letting other researchers verify findings directly (openwall.com).
  • GitHub suspended the implicated accounts and disabled Tukaani's repositories, including the releases page, cutting off distribution of the infected tarballs (news.ycombinator.com).
  • Alpine shipped a fix within hours of the disclosure being discussed on Hacker News (news.ycombinator.com).
  • Community members cross-referenced the attacker's public key across AUR, Arch, and openSUSE, and independently found the separate Landlock sandbox sabotage commit (news.ycombinator.com).

Action items

  • Remove the implicated contributor's public key from keyrings, approved-publisher lists, and package metadata — already underway for Arch, openSUSE, and AUR packages (pacman-static, mingw-w64-xz) (news.ycombinator.com).
  • Treat any package touched by the implicated contributor over their roughly two years of involvement as suspect until independently verified, per the Fedora packager's comment that older xz versions warrant scrutiny too (news.ycombinator.com).
  • Weigh repository suspension against archiving: commenters raised whether archiving instead of fully disabling repos would better balance containment against enabling continued forensic analysis; the sources don't say whether this was resolved (news.ycombinator.com).
  • Build automated diffing between released tarball contents and the corresponding git tree to flag unexplained additions like the build-to-host.m4 change — proposed in discussion, not confirmed as adopted (news.ycombinator.com).
  • Add automated verification that configure-time and sandboxing checks (like the sabotaged Landlock check) actually pass on systems where the capability is expected, rather than silently failing closed (news.ycombinator.com).
  • The sources do not say what formal, project-wide changes the xz/Tukaani project itself committed to, since its repositories were disabled at the time of these reports.

FAQ

Which xz versions had the backdoor?

xz/liblzma 5.6.0 and 5.6.1. The malicious code was in the distributed release tarballs, not in GitHub's auto-generated source archives.

How was the xz backdoor discovered?

Andres Freund, doing unrelated Postgres benchmarking, noticed SSH logins on Debian sid using unusual CPU and triggering valgrind errors. SSH auth to localhost took about 0.807 s instead of 0.299 s.

Why could the xz backdoor reach sshd?

OpenSSH doesn't link liblzma directly, but several distributions patch it for systemd notification support, and libsystemd depends on liblzma. That indirect chain exposed sshd.

xzliblzmasupply chainbackdoorsecuritylinuxsshexploit

Sources

  1. 01
    Backdoor in upstream xz/liblzma leading to SSH server compromise
  2. 02
    security - backdoor in upstream xz/liblzma leading to ssh server compromise

Explore the product

Untested by us. Check what's included, the license and refund terms before you buy.

Ready Client Sites for prebuilt websites

See Ready Client Sites details

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Explore the product

Untested by us. Check what's included, the license and refund terms before you buy.

Ready Client Sites for prebuilt websites

See Ready Client Sites details

Keep reading

  • volta vs fnm: Should You Switch? 14ms vs 17ms

    volta 2.0.2 vs fnm 1.39.0 switching Node 20.19.2 ↔ 22.14.0: session A-then-B median 13.9 ms vs 17.0 ms; steady node -v 7.4 ms vs 6.4 ms (direct 4.7 ms).

    Hands-on5 Oct 20265 min read

  • Angular router SSR: upgrade for RouterLink queryParams DoS (1 Oct 2026)

    On 1 Oct 2026 Angular published GHSA-57xq-rjx2-v5xh: High DoS in @angular/router when SSR + RouterLink queryParamsHandling merge/preserve retain UrlTree query maps in heap. Patched in 21.2.25 and 22.2.1. Client-only SPAs unaffected. ShopperCove upgrade checklist only—no exploit payloads; no affiliate.

    Summary5 Oct 20264 min read

  • What Does Next.js 16.3.8 Fix? 7 Security Bugs

    Next.js 16.3.8 (30 Sep 2026) covers image SSRF and cache bugs. CVE-2026-94545, the next/og RCE, was patched in 16.3.6 and is not a 16.3.8 fix.

    Summary3 Oct 20268 min read