psf-apt-nov2026-check(8)
APT: a package download can be swapped after APT has verified it (v1)
CVE-2026-109518
If this software is helpful, consider a donation to our 501c3 nonprofit:
https://privacysafe.foundation
APT, the package manager of Debian, Ubuntu and their derivatives, can merge two
different package downloads when an HTTP redirect gives them the same address, and
it reuses a file through a hard link when it retries a download. Someone who can
alter the HTTP traffic between the host and the archive (an attacker on the network
path, a malicious mirror or a proxy) can use redirects and ordinary temporary server
errors to make APT retry, and replace a package after APT has checked it. The
replaced package is installed as root. CWE-62 (hard link) and CWE-367 (a time of check
to time of use race), CVSS 4.0 score 7.7 (High); the APT developers call it critical. Reported by Max Justicz, disclosed on 4 November 2026.
The attack needs both of these at once: APT follows redirects (it does by default)
and Acquire::Retries is above 0. The default is 3 on Debian 12 and Ubuntu 22.04 and
later, so Debian 11, Ubuntu 20.04 and older are not exposed in their default
configuration, unless a script or an image turned retries on.
Fixed APT releases (the CVE record), by release line:
3.3.6, 3.2.1, 3.0.4, 2.8.4, 2.6.2, 2.4.15, 2.2.5, 2.0.12, 1.8.2.4, 1.6.19,
1.4.12 and 1.2.36. APT 1.8.3 through 1.8.5 are affected and have no fixed 1.8
release.
Debian: 13 (trixie) 3.0.4, DSA-6607-1. 12 (bookworm) 2.6.2, DLA-4880-1. 11
(bullseye) 2.2.5, published by the APT developers after its long term
support ended on 31 August 2026. Unstable has 3.3.6; testing (forky) was
still on the affected 3.3.5 in Debian's security tracker.
Ubuntu: 26.10 3.3.3ubuntu0.1, 26.04 LTS 3.2.1ubuntu0.1, 24.04 LTS 2.8.4ubuntu0.1,
22.04 LTS 2.4.15ubuntu0.1, Ubuntu Pro 20.04 2.0.12+esm1.
No workaround is published by the advisories. The stopgap that follows from the
description is Acquire::Retries "0", which removes one of the two conditions (APT
then does not retry a failed download, which can make updates less reliable on a
poor connection). Updating APT is the fix.
Usage:
./apt-nov2026-check.sh [command]
check (default) read-only. Reads the installed APT version, judges it against the
fixed releases, reads the effective Acquire::Retries and redirect
settings, and lists where this host downloads from. Exit 0 = APT is
fixed, or it is not fixed but a condition of the attack is off (a
warning says so), or APT is not installed. 1 = vulnerable and both
conditions are on. 2 = it could not be judged (a development
version between the published ranges, or APT would not answer).
hunt read-only. APT's published advisories name no indicator, so this
looks for what the flaw would leave: a cached package whose
SHA-256 differs from the one in the index for the same name,
version and architecture, and files in the package and list
caches that have more than one hard link (a healthy cache has
none). A clean hunt is not clearance. Exit 0 = nothing found, 1 =
a lead, 2 = it could not read what it needs.
mitigate [--dry-run] (root) changes the host. Writes the file
/etc/apt/apt.conf.d/99psf-cve-2026-109518-retries with
Acquire::Retries "0", then asks apt-config for the effective value.
If another file or setting overrides it, the new file is removed
again and the command says which one. Nothing else is touched. This
is a stopgap, not the fix: update APT, then run rollback.
rollback [--dry-run] (root) removes the file that mitigate wrote (and only that
file; --force removes it even if someone edited it).
version print the script version.
Update first, with retries off for the update itself:
sudo apt-get -o Acquire::Retries=0 update
sudo apt-get -o Acquire::Retries=0 install --only-upgrade apt
Environment: STATE_DIR (default /var/lib/psf-security-patches/apt) holds the manifest.
APT_CONF_DIR (default /etc/apt/apt.conf.d) is where mitigate writes.
ARCHIVES_DIR and LISTS_DIR replace APT's package and list folders for
hunt. APT_HELPER (default /usr/lib/apt/apt-helper) reads compressed
index files. OS_RELEASE (default /etc/os-release) names the release.
PSF_LOCK_WAIT seconds a run that changes the host waits for another one that is already
changing it (default 30), then stops with exit 2; the lock is STATE_DIR/.lockThe Security Patches software and this documentation are dedicated to the public domain under CC0 1.0 Universal. Other pages on privacysafe.app/docs are CC BY-SA 4.0 unless the page says otherwise.