APT flaw lets an on-path attacker swap packages for root
CVE-2026-109518 lets anyone who can tamper with HTTP mirror traffic slip an unverified package past APT on Debian and Ubuntu. Fixed versions, a workaround and checks.
By Yaali. November 6, 2026, 6 min read, Vulnerabilities, Patching.
On November 4, Debian and Ubuntu shipped fixed versions of APT, the package manager behind apt, apt-get, aptitude and Ubuntu's graphical updaters. The bug, CVE-2026-109518, was reported by Max Justicz. It lets an attacker who can tamper with HTTP traffic between a machine and its package mirror get APT to install a package it never verified. Package maintainer scripts run as root, so the result is code execution as root on the machine being updated.
Canonical rates it High with a CVSS 4.0 score of 7.7. APT maintainer Julian Andres Klode labelled it critical in his announcement. It is exploitable in the default configuration on Debian 12 and later and on Ubuntu 22.04 LTS and later, and on older releases only where someone has set Acquire::Retries. None of the advisories report exploitation in the wild. Most exposed are machines that update over plain HTTP through networks you do not control: laptops on hotel Wi-Fi, cloud instances using third-party mirrors, container builds behind a shared proxy.

How it works
APT's trust model does not rely on the transport. It downloads a signed InRelease file, checks its GPG signature, and uses the SHA256 hashes listed there (through the Packages index) to check every .deb it fetches. Tampering in transit should therefore show up as a hash mismatch, even over plain HTTP.
CVE-2026-109518 breaks the link between "this file was checked" and "this file is what gets installed". Debian's advisory, DSA-6607-1, describes two parts. First, when an HTTP redirect makes two separate package downloads point to the same URI, APT merges them, and the files on disk end up as hard links: two names for the same data. Second, when an HTTP download is resumed after an error, APT opened the existing partial file for writing in place. If that file is a hard link to a package APT has already checked, the attacker's bytes land in the checked file too.
Klode's write-up sums up the recipe: HTTP redirects plus transient server errors drive APT's retry logic, and during those retries APT replaces existing hard links with an attacker-chosen payload. The hash check has already passed, so dpkg installs whatever is now in the file, and the package's postinst script runs as root.
The retry step is why the release split matters. Resuming only happens when Acquire::Retries is non-zero. Its default became 3 in APT 2.3.2, which is the APT generation in Debian 12 and Ubuntu 22.04. Debian 11 and Ubuntu 20.04 default to zero retries, unless an old script or image set the option to cope with flaky mirrors.
The fix, commit 5af16a8 in APT 3.3.6, makes the download methods open target files exclusively. A resumed download now reads the partial data, unlinks the old path, and writes a fresh file, so nothing can be written through a hard link.
The same releases fix several out-of-bounds bugs in the .deb parser, solver and DNS SRV code. Klode expects those to matter mainly as crashes in privileged daemons that parse untrusted packages, such as PackageKit or aptdaemon.
Who can pull this off
The attacker needs to control HTTP responses for your package downloads. That covers anyone on the network path (a rogue Wi-Fi access point, a compromised router or proxy) and anyone running a mirror you use. Canonical's guidance points out that HTTPS stops the first group but not the second: a malicious mirror sits at the end of the encrypted connection and can serve the redirects and errors itself.
Canonical says Snap packages and non-HTTP transports such as FTP are not affected. Ubuntu also warns that distributions built on Debian or Ubuntu are affected, without naming them, so check your derivative's own tracker.
What to do
Fixed versions
| Release | Fixed apt version | Advisory |
|---|---|---|
| Debian 13 trixie | 3.0.4 | DSA-6607-1 |
| Debian 12 bookworm | 2.6.2 | DLA-4880-1 |
| Debian testing (forky) and sid | 3.3.6 | Debian tracker |
| Ubuntu 26.10 | 3.3.3ubuntu0.1 | USN-8996-1 |
| Ubuntu 26.04 LTS | 3.2.1ubuntu0.1 | USN-8996-1 |
| Ubuntu 24.04 LTS | 2.8.4ubuntu0.1 | USN-8996-1 |
| Ubuntu 22.04 LTS | 2.4.15ubuntu0.1 | USN-8996-1 |
| Ubuntu 20.04 LTS | 2.0.12+esm1 (Ubuntu Pro) | USN-8996-1 |
| Ubuntu 18.04 LTS | 1.6.19+esm1 (Ubuntu Pro) | USN-8996-1 |
| Ubuntu 16.04 and 14.04 LTS | 1.2.36+esm1 and 1.0.1ubuntu2.24+esm4 (Pro Legacy add-on) | USN-8996-1 |
Klode's announcement also lists upstream fixes on the 1.4, 1.8 and 2.2 branches (1.4.12, 1.8.2.4, 2.2.5) for Debian's extended LTS releases.
Check what you have with apt list --installed '?source-package(^apt$)', or dpkg-query -W apt on a single host, and compare it with the table.
Update without opening the hole you are closing
The upgrade itself goes through the vulnerable code. Canonical recommends switching retries off for that one run:
sudo apt update && sudo apt install -o Acquire::Retries=0 --only-upgrade '?source-package(^apt$)'
Use sudo apt upgrade -o Acquire::Retries=0 for a full upgrade. On hosts you cannot patch today, put Acquire::Retries "0"; in a file under /etc/apt/apt.conf.d/ until you can, and remove it after the fix is in. Also search for older overrides that would turn retries back on: grep -ri retries /etc/apt/apt.conf /etc/apt/apt.conf.d/.
Unattended-upgrades, on by default on Ubuntu since 16.04, should pick up the fix within about 24 hours. Run the version check above to confirm it has.
Move mirrors to HTTPS
Switching sources to https:// takes the on-path attacker out of the picture for this bug and the next one. deb.debian.org, security.debian.org and the official Ubuntu archive hosts all serve HTTPS. Canonical's blog gives a sed one-liner for the Ubuntu hosts in /etc/apt/sources.list and the .sources files under /etc/apt/sources.list.d/. Some country and community mirrors do not support HTTPS, so run apt update afterwards and fix any source that fails. Do this in base container images too, because apt-get install in a Dockerfile runs as root against whatever mirror the image names.
Check whether a host was hit
No vendor has published indicators. These checks follow from how the attack works:
- Compare cached packages with the archive's hashes. For each file still in
/var/cache/apt/archives/, thesha256sumshould match theSHA256field thatapt-cache show <package>=<version>prints. A mismatch on a package APT installed is a strong signal. - If outbound HTTP goes through a proxy or
apt-cacher-ng, look in its logs for.debrequests answered with a 3xx redirect followed by a 5xx error and a ranged retry from the same client. - Read
/var/log/apt/history.logandterm.logfor installs at times nobody scheduled.
debsums and dpkg --verify will not help here: a swapped package installs its own checksum list. A host that fails these checks should be rebuilt, not cleaned, and any credentials it held rotated.
Where the signature check stops
The archive signatures were valid and APT checked them correctly. The bypass worked because the file changed after the check. Two habits limit the damage when the next bug like this turns up. Use HTTPS to a mirror you trust, so the first layer does not depend on the second being perfect. And treat the package manager as part of your patch inventory, including in container base images that nobody rebuilds unless something forces them to.
If you want a second pair of eyes on how your Linux fleet and build images pull updates, our safeguarding and hardening team reviews mirror, proxy and update configuration, and cloud and Kubernetes security covers the images behind your workloads. Open the chat and Yaali, our AI agent, will pass your question to an engineer.
Sources: Debian DSA-6607-1, Debian security tracker, Julian Andres Klode on the Debian deity list, APT fix commit 5af16a8, Ubuntu CVE page, Ubuntu USN-8996-1, Ubuntu blog: APT vulnerability fixes available, OSV entry, Linuxiac on APT 3.3.6, The Hacker News.
Read next
- OpenAI's AI pipeline wrote 948 Linux root exploits
- OpenSSH 10.6p2: long passwords open locked Alpine accounts
- Android November patches: 2026-11-01 or 2026-11-05?
Back to the blog, or tell us about your system in the chat. Yaali, our AI agent, answers first and brings in an engineer.