CVE-2024-3094 — xz-utils backdoor
A maintainer with multi-year commit history shipped versions
5.6.0 and 5.6.1 of xz-utils containing a backdoor in
liblzma. When the library was loaded into sshd (via
systemd’s libsystemd linkage), the backdoor extracted a
hidden RSA-shaped trigger from the SSH connection and granted
the attacker code execution. The vulnerability was discovered
because a microbenchmark unrelated to the backdoor showed a
half-second slowdown on SSH connections.
This is one of the closest near-misses in supply-chain history. The backdoor shipped to a few rolling-release distros before discovery; most stable distros never picked it up.
Affected versions
- xz-utils 5.6.0 and 5.6.1 — vulnerable.
- xz-utils 5.4.6 / 5.4.x — clean.
- xz-utils 5.6.2+ — clean (the backdoor was reverted).
The backdoor activates only when:
- The build is run on a glibc-using x86_64 Linux system.
- The build is invoked through autotools (the malicious code is
in the
m4/build-to-host.m4macro from the release tarballs, not the git repo). - The resulting
liblzmais linked into a process that also loadslibsystemdor matches a small set of binary signatures (sshdis the named target).
This is the most thorough attack-narrow precondition list any single CVE has had. It still pays off if you’re running an affected distro.
Indicator-of-exposure
The system is exposed if:
- The installed
xz-utils(or the underlyingliblzma) is 5.6.0 or 5.6.1. - The system is glibc x86_64 Linux.
- The
sshdbinary on the system loadsliblzma(typically throughlibsystemd).
Quick check:
# Version
xz --version
# Does sshd load liblzma transitively?
ldd "$(which sshd)" | grep lzmaIf the version is in range and sshd links liblzma, treat
the system as compromised — credentials, host keys, and
anything in process memory at the time of any SSH connection
are suspect.
Remediation strategy
The fix is all of:
- Roll back
xz-utilsto 5.4.x (or upgrade to 5.6.2+ on distros that ship it). - Verify the installed binary is from the distro’s clean build. The malicious tarballs were signed; signature alone is not enough.
- Treat the host as compromised if it ran an affected
sshd:- Rotate every credential the host had access to (cloud IAM keys, deploy tokens, signed certs).
- Rotate SSH host keys.
- Rotate any in-memory secrets (recently-decrypted credentials, mTLS private keys, token caches).
- Audit auth logs for unexplained connections during the exposure window.
- Rebuild any artifact that was built on an affected host while it was affected. The backdoor allows arbitrary command execution; you cannot trust artifacts produced during the exposure window.
This is not a routine bump. The CVE narrative is a supply-chain compromise; the response is supply-chain incident response.
The prompt
You are remediating CVE-2024-3094 (xz-utils backdoor) on this
host or in this system image. Output exactly one of:
- A PR / change request rolling the package back, plus an
incident-response checklist for the operator.
- A TRIAGE.md if the system is in the affected window and
needs immediate human-led incident response.
This recipe is **not** a routine package bump. If exposure is
confirmed, do not auto-remediate; produce the incident
checklist and stop.
## Step 0 — Detect
1. Read the system's `xz-utils` / `liblzma` version (via the
distro package manager, plus `xz --version` and
`strings $(which xz) | grep -E '5\\.[456]'`).
2. Determine whether `sshd` on this system loads `liblzma`:
`ldd $(which sshd) | grep lzma`.
3. Check the host's distro and version against published
advisories (the affected window varies — Debian sid /
Fedora 40 / Kali / openSUSE Tumbleweed all picked up the
bad version at different times).
## Step 1 — Classify
- **Not affected:** Version is 5.4.x or ≥5.6.2; or `sshd`
doesn't load `liblzma`. Document and stop.
- **Affected, never reachable from the network:** The host
has affected `xz-utils` but `sshd` was firewalled-off /
disabled / not running during the exposure window. Roll
back the package; rotate any local secrets that were
in-memory; document.
- **Affected, network-reachable sshd:** Treat as compromised.
Stop here. Do not auto-remediate. Write a TRIAGE.md with
the incident-response checklist and page the security
on-call.
## Step 2 — Roll back the package (when classification is
"not network-reachable affected")
1. For Debian / Ubuntu rolling: `apt install xz-utils=5.4.5-*`
(or the distro's clean-version pin). For Fedora 40:
the distro shipped a rebuild — `dnf upgrade xz xz-libs`.
For Arch / openSUSE Tumbleweed / Kali: follow the
distro-specific roll-back advisory.
2. Verify the new package signature matches the distro's
clean build.
3. Restart `sshd` (and any other process that loaded
`liblzma`).
## Step 3 — Verify
1. `xz --version` prints a clean version.
2. `ldd $(which sshd) | grep lzma` shows the new path.
3. The host's `liblzma` SHA matches the distro's published
clean SHA.
## Step 4 — Incident-response checklist (in the TRIAGE.md
when classification is "compromised")
The checklist must include:
- Rotate SSH host keys.
- Rotate every long-lived credential the host had access to:
cloud IAM, registry tokens, deploy keys, mTLS private
keys.
- Rotate any in-memory secrets that were decrypted during the
exposure window.
- Pull the auth log and search for unexplained sessions.
- Identify and rebuild every artifact that was produced on
this host during the exposure window.
- Report the incident through the org's IR channel.
The checklist is human-driven. The agent does not run any
of these steps.
## Stop conditions
- The system is in the "compromised" classification — write
the checklist and stop.
- The distro's clean roll-back path is unclear and no
upstream advisory exists for this distro. Triage.
- The host has multi-tenant exposure (shared host, multiple
customers) — escalate before touching anything.
## Scope
- Do not roll back any package other than xz-utils / liblzma.
- Do not silently restart services without recording which.
- Do not modify SSH configuration other than as part of a
documented IR action.
- Do not draft credential rotation actions; the IR checklist
names them, the operator runs them.Verification — what the reviewer looks for
- The version verification ran and produced a clean number.
- The
lddcheck confirmedsshdlinked the new lib. - For compromised hosts: the IR checklist was followed (review the linked artefacts), not just the package rollback.
- The reviewer does not trust the agent’s “not affected” classification without re-running the detection commands themselves.
Watch for
- Distro-specific repackages. Some distros backported the fix into 5.6.x rather than rolling back. Don’t assume “5.6” is bad without checking the distro’s published clean SHA.
- Container images built during the exposure window. A container image baked from an affected base inherits the backdoor. Rebuild every affected image; treat the affected image’s published copies as potentially compromised.
- CI runners. A self-hosted CI runner with an affected
xz-utilsand a publicly-reachablesshdis exactly the shape this attack targeted. Audit those first. liblzmais not always reached throughsshd. Other binaries linkliblzmafor legitimate reasons; the backdoor’s preconditions narrow the impact, but other CVEs in the future may not.- Reproducibility from the git repo vs. tarball. The malicious code was in the release tarball but not in the git repository. Build provenance (“we built from git”) was the durable check; vendor signatures alone were not.
Related
- Artifact Cache & Mirror Quarantine — the workflow for evicting the bad artifact from internal mirrors.
- Threat Model → Agent-infrastructure supply-chain compromise — why this case is treated separately from routine CVEs.
- Base Image & Container Layer Remediation — for evicting the affected version from container bases.