Stable Debian does not get APT 3.3.6 for CVE-2026-109518. That version is the fix in unstable, and most of the coverage of this bug quotes it as if it applied everywhere. Debian 13 gets apt 3.0.4 from trixie-security, Debian 12 gets 2.6.2 from bookworm-security, and Ubuntu ships its own fixed builds under USN-8996-1. If you only compare your version against 3.3.6, every patched trixie box will look vulnerable to you.
Below are the fixed apt version per release, commands that show if a host is exposed, the Acquire::Retries check this flaw depends on, the upgrade and a script for a whole fleet. Every command below ran on 4 and 5 November 2026 on Debian 13, Ubuntu 26.04 and Ubuntu 24.04 VMs and a minimal Debian 12 container, including the upgrade on Debian 13, Debian 12 and Ubuntu 24.04.
Know the fixed APT version for your release
CVE-2026-109518 lets an attacker who can tamper with the HTTP traffic between APT and its archive (a hostile network, a malicious mirror or a proxy) swap a package after APT has already verified it. The Debian advisory DSA-6607-1 says APT can merge two downloads once an HTTP redirect gives them the same URI, and that improper file handling on a resumed download lets the attacker replace the package. Packages install as root, so the result is code execution as root. Max Justicz reported it, and the upstream fix makes the download methods open their target files exclusively.
Check your installed apt against the row for your release, not against the newest upstream number. Debian versions come from the Debian security tracker, and the Ubuntu builds come from Ubuntu’s CVE tracker and USN-8996-1:
| Release | Vulnerable apt | Fixed apt | Advisory |
|---|---|---|---|
| Debian 13 (trixie) | 3.0.3 | 3.0.4 | DSA-6607-1 |
| Debian 12 (bookworm) | 2.6.1 | 2.6.2 | DLA-4880-1 |
| Debian unstable (sid) | 3.3.5 | 3.3.6 | none, uploaded to unstable |
| Debian testing (forky) | 3.3.5 | 3.3.6 once it migrates | none |
| Ubuntu 26.10 (stonking) | 3.3.3 | 3.3.3ubuntu0.1 | USN-8996-1 |
| Ubuntu 26.04 (resolute) | 3.2.0 | 3.2.1ubuntu0.1 | USN-8996-1 |
| Ubuntu 24.04 (noble) | 2.8.3 | 2.8.4ubuntu0.1 | USN-8996-1 |
| Ubuntu 22.04 (jammy) | below 2.4.15ubuntu0.1 | 2.4.15ubuntu0.1 | USN-8996-1 |
| Ubuntu 20.04 (focal) | below 2.0.12+esm1 | 2.0.12+esm1 | USN-8996-1, Ubuntu Pro |
| Ubuntu 18.04 (bionic) | below 1.6.19+esm1 | 1.6.19+esm1 | USN-8996-1, Ubuntu Pro |
Upstream cut fixed releases on every maintained branch (2.6.2, 2.8.4, 3.0.4 and 3.2.1 among them), as listed in the APT-2026-11-01 announcement. The same update bundles several out-of-bounds read fixes that upstream rates as denial of service at worst, mostly for daemons like PackageKit that parse untrusted .deb files as root. It also stops unbounded memory use when the 2.6, 2.8 and 3.0 series retry delayed downloads. The trixie 3.0.4 changelog lists those fixes without CVE numbers, so CVE-2026-109518 is the one id to look for.
Check the installed APT version
Refresh the package lists first, because apt policy can only show a fixed candidate if your host has seen the security pocket that carries it. Then print the version and the policy:
sudo apt update
apt --version
apt policy apt
Our Debian 13 host was still on 3.0.3, with 3.0.4 waiting in trixie-security:
apt 3.0.3 (amd64)
apt:
Installed: 3.0.3
Candidate: 3.0.4
Version table:
3.0.4 500
500 mirror+file:/etc/apt/mirrors/debian-security.list trixie-security/main amd64 Packages
*** 3.0.3 500
500 mirror+file:/etc/apt/mirrors/debian.list trixie/main amd64 Packages
100 /var/lib/dpkg/status
Read the three stars, not the top line. They mark the installed version, and the higher entry above it is the build you have not taken yet. A Candidate that matches the table row means the patched package is reachable and one command away. A Candidate equal to Installed on a vulnerable version means your sources do not include the security pocket, or your mirror has not synced. Upgrading will do nothing until that changes.
The full run on the Debian 13 box includes the apt update lines that show which archives it reached:

Notice that the trixie cloud image already fetches from https://deb.debian.org through its mirror list. Neither vendor lists HTTPS sources as a mitigation, and the Ubuntu description names a malicious mirror or proxy among the attacker positions, so treat an HTTPS host as vulnerable until apt is upgraded. The Debian 12 host ran 2.6.1 with 2.6.2 as its candidate from http://security.debian.org, which is the plain HTTP case the advisory describes.

The three stars sit on 2.6.1 here, with the bookworm-security build above it, so this box needs the same one-package upgrade as trixie. The Ubuntu hosts are covered in their own section further down, because their story differs.
Check the APT retry setting on each host
The attack needs APT to retry failed downloads. The Ubuntu CVE entry says it requires a non-zero Acquire::Retries, and that 3 has been the default since Debian 12 and Ubuntu 22.04, so older releases are only exposed when someone set the option. The upstream APT note adds that the default arrived in APT 2.3.2 and that many user scripts set it on older releases anyway. The obvious check is to grep the merged configuration:
apt-config dump | grep -i retries
On all four of our hosts that printed nothing at all, and an empty result is the trap here. The default of 3 is compiled into APT rather than written to a file under /etc/apt/apt.conf.d/, so apt-config dump has no line to show. You only see the option when someone set it explicitly, which means an empty grep tells you that you’re running the default, not that retries are off.
To see the effective value, point APT at a local port where nothing listens and turn on its retry debugging. This touches no real repository and leaves your package lists alone:
echo "deb http://127.0.0.1:8099/ x main" > /tmp/retry-test.list
sudo apt-get update -o Debug::Acquire::Retries=true -o Dir::Etc::sourcelist=/tmp/retry-test.list -o Dir::Etc::sourceparts=- -o APT::Get::List-Cleanup=0 2>&1 | grep -E 'Delaying|^Err'
Three delayed retries, then the final error, is what a default install looks like:
Delaying http://127.0.0.1:8099 x InRelease by 1 seconds
Delaying http://127.0.0.1:8099 x InRelease by 2 seconds
Delaying http://127.0.0.1:8099 x InRelease by 4 seconds
Err:1 http://127.0.0.1:8099 x InRelease
The capture from the Debian 13 host shows both checks side by side, the silent grep and the three retries.

Debian 12 (apt 2.6.1), Ubuntu 24.04 (2.8.3) and Ubuntu 26.04 (3.2.0) printed the same three lines. This is the Ubuntu 24.04 run, after an empty apt-config dump | grep -i retries:
Delaying http://127.0.0.1:8099 x InRelease by 1 seconds
Delaying http://127.0.0.1:8099 x InRelease by 2 seconds
Delaying http://127.0.0.1:8099 x InRelease by 4 seconds
Err:1 http://127.0.0.1:8099 x InRelease
So every default install we tested meets the retry condition:
- Debian 13, apt 3.0.3: no config line, 3 retries
- Debian 12, apt 2.6.1: no config line, 3 retries
- Ubuntu 26.04, apt 3.2.0: no config line, 3 retries
- Ubuntu 24.04, apt 2.8.3: no config line, 3 retries
No mitigation is published. DSA-6607-1 tells you to upgrade, Ubuntu’s entry describes the retry setting only as a condition of the attack, and the upstream note says the bug relies on it without offering a workaround. Read the retry check as a way to know which hosts meet the documented conditions, and treat the upgrade as the only fix.
Check a whole fleet with one script
Comparing version strings by eye across releases is where mistakes happen, especially with Ubuntu’s ubuntu0.1 suffixes. dpkg --compare-versions applies Debian’s real ordering rules. A short script that maps each codename to its first fixed build therefore gives you a reliable yes or no. Create it.
sudo vim /usr/local/bin/apt-cve-check
Paste the script. It exits 1 on a vulnerable host and 2 on a codename it doesn’t know, so you can use it in a monitoring check as well as by hand:
#!/bin/sh
# Compare the installed apt with the first fixed build for CVE-2026-109518
. /etc/os-release
case "$VERSION_CODENAME" in
bookworm) fixed=2.6.2 ;;
trixie) fixed=3.0.4 ;;
forky|sid) fixed=3.3.6 ;;
jammy) fixed=2.4.15ubuntu0.1 ;;
noble) fixed=2.8.4ubuntu0.1 ;;
resolute) fixed=3.2.1ubuntu0.1 ;;
stonking) fixed=3.3.3ubuntu0.1 ;;
*) echo "$(hostname) $VERSION_CODENAME: no fixed version on record, check your vendor"; exit 2 ;;
esac
installed=$(dpkg-query -W -f='${Version}' apt)
if dpkg --compare-versions "$installed" lt "$fixed"; then
echo "$(hostname) $VERSION_CODENAME apt $installed VULNERABLE (fixed in $fixed)"
exit 1
fi
echo "$(hostname) $VERSION_CODENAME apt $installed patched"
Make it executable:
sudo chmod +x /usr/local/bin/apt-cve-check
Run it locally, then feed the same file to remote hosts over SSH with sh -s, so nothing has to be installed on them first. Replace the host names with your own:
apt-cve-check
for h in u2404-01 u2604-01; do ssh "$h" 'sh -s' < /usr/local/bin/apt-cve-check; done
Before any patching, our lab came back vulnerable on every host, each line naming the build it needs:
deb13-01 trixie apt 3.0.3 VULNERABLE (fixed in 3.0.4)
u2404-01 noble apt 2.8.3 VULNERABLE (fixed in 2.8.4ubuntu0.1)
u2604-01 resolute apt 3.2.0 VULNERABLE (fixed in 3.2.1ubuntu0.1)
On the Debian 13 admin host, that run looked like this.

The Debian 12 host printed deb12-01 bookworm apt 2.6.1 VULNERABLE (fixed in 2.6.2) on its own run. A codename the script doesn’t map, such as the 27.04 development release, exits 2 rather than guessing, and if Ubuntu later ships a different build string, update its row before trusting a VULNERABLE line. Keep the exit code in mind once you have more than a handful of servers, because it gives your config management or monitoring a pass or fail without parsing any text. The patch step below runs the same script again as its proof.
Patch APT on Debian 13 and Debian 12
Upgrade only APT and the libraries it pulls in. A full apt upgrade is fine too. On a host with 94 pending updates like ours, though, a narrow upgrade gets the security patch in now without dragging a kernel and a reboot into the same change window. If you haven’t used --only-upgrade before, our guide on upgrading a single package with apt covers how it behaves. Run it after the apt update from the check step:
sudo apt install --only-upgrade -y apt
On Debian 13 that upgraded three packages, because apt-utils is pinned to the same libapt version and comes along:
Upgrading:
apt apt-utils libapt-pkg7.0
Summary:
Upgrading: 3, Installing: 0, Removing: 0, Not Upgrading: 91
Download size: 2904 kB
Space needed: 3072 B / 18.7 GB available
Get:2 https://deb.debian.org/debian-security trixie-security/main amd64 libapt-pkg7.0 amd64 3.0.4 [1114 kB]
Get:3 https://deb.debian.org/debian-security trixie-security/main amd64 apt amd64 3.0.4 [1453 kB]
Get:4 https://deb.debian.org/debian-security trixie-security/main amd64 apt-utils amd64 3.0.4 [337 kB]
Confirm the new version, rerun the check script, and then let the package changelog prove you got the security build rather than an unrelated point release.
apt --version
apt-cve-check
zgrep -m1 -B2 -A1 CVE-2026-109518 /usr/share/doc/apt/changelog.gz
Both Debian hosts printed the same changelog entry, with the exclusive-open change listed against the CVE, and the script flipped to patched:
apt 3.0.4 (amd64)
deb13-01 trixie apt 3.0.4 patched
* SECURITY UPDATE: Download verification bypass
- methods/*.cc: Open target files exclusively
- CVE-2026-109518
* SECURITY UPDATE: Out-of-bounds accesses
The full Debian 13 session, from the upgrade to the changelog line, is in the capture below.

Debian 12 is the same command with a smaller transaction. A minimal bookworm system has no apt-utils, so only apt and libapt-pkg6.0 moved from 2.6.1 to 2.6.2, both pulled from bookworm-security:

The CVE fix lives in APT’s download methods, which start fresh for every download, so the next apt or unattended-upgrades run is already protected. The bundled out-of-bounds fixes sit in libapt-pkg, though, and a long-running daemon such as packagekitd keeps the old library mapped until it restarts, so let needrestart restart it or reboot in your next window. A full bookworm server usually has apt-utils installed and will upgrade three packages here, like trixie did. Bookworm is in Debian LTS now, which is why its fix arrives as a DLA rather than a DSA, but it lands in the same bookworm-security suite your sources already list.
Patch Ubuntu 26.04 and 24.04
Ubuntu fixed CVE-2026-109518 under USN-8996-1, and its tracker now marks every listed release Fixed. The builds you need are 3.2.1ubuntu0.1 on 26.04, 2.8.4ubuntu0.1 on 24.04, 2.4.15ubuntu0.1 on 22.04 and 3.3.3ubuntu0.1 on 26.10, matching the table at the top. Ubuntu 20.04 (2.0.12+esm1), 18.04 (1.6.19+esm1), 16.04 (1.2.36+esm1) and 14.04 (1.0.1ubuntu2.24+esm4) get ESM builds, which only reach machines attached to Ubuntu Pro, and 16.04 and 14.04 also need the Legacy add-on. Our apt-cve-check script has no rows for those ESM releases, so it exits 2 on them by design; check them against the table by hand.
The fix took a few hours to reach servers, which is why our 4 November fleet check above still found 2.8.3 and 3.2.0. If your hosts showed no candidate before about 20:00 UTC that day, this is why. The timeline ran across 4 November 2026.
- 14:25 UTC, 4 November: fixed builds published to the security pockets on Launchpad
- 17:04 UTC, 4 November: security.ubuntu.com indexes still dated 3 November
- About 20:00 UTC, 4 November: new noble-security and resolute-security indexes signed
- By 20:50 UTC, 4 November: tracker rows marked Fixed and linked to USN-8996-1, which is itself dated 4 November
On 5 November a fresh Ubuntu 24.04 VM saw the fixed build straight after sudo apt update, with 2.8.4ubuntu0.1 from noble-security sitting above the installed 2.8.3:

The upgrade is the same command as on Debian. On 24.04 it moved three packages, apt, apt-utils and the library, which carries the t64 name libapt-pkg6.0t64 there:
sudo apt install --only-upgrade -y apt
Ubuntu’s needrestart then restarted packagekit.service on its own, which takes care of the daemon caveat from the Debian section. The same apt --version, apt-cve-check and changelog checks confirm the fix:
apt 2.8.4 (amd64)
u2404-01 noble apt 2.8.4ubuntu0.1 patched
* SECURITY UPDATE: Download verification bypass
- methods/*.cc: Open target files exclusively
- CVE-2026-109518
* SECURITY UPDATE: Out-of-bounds accesses
Notice that apt --version prints only the upstream 2.8.4, so check the full package version with apt policy or the script rather than trusting that line on Ubuntu. The whole 24.04 run is in the capture below.

Our Ubuntu 26.04 VM never needed the command. The template’s first boot runs a cloud-init package upgrade, and on 5 November that pulled 3.2.1ubuntu0.1 before we logged in. The dpkg log is the quickest way to prove when a host took the fix, whoever installed it:
grep " upgrade apt:" /var/log/dpkg.log
You should see the jump from 3.2.0 to the fixed build, here at 03:09 UTC.
2026-11-05 03:09:03 upgrade apt:amd64 3.2.0 3.2.1ubuntu0.1
The full 26.04 session below adds the version, policy, script and changelog checks you’d run on your own hosts.

Older releases need a closer look. The tracker description still says releases before 22.04 are unaffected in a default configuration, because Acquire::Retries only became a default in APT 2.3.2. A 20.04 or older box that sets the option in a script or config file is exposed all the same, and the fix for it comes only through Ubuntu Pro.
Keep APT patches flowing
All three of our VM images (Debian 13, Ubuntu 24.04 and Ubuntu 26.04) shipped with unattended-upgrades active and APT::Periodic::Unattended-Upgrade "1" set. That runs security updates on a daily timer. We stopped those timers in the lab to keep the vulnerable state long enough to capture it. On your servers, leave them running, because the next APT flaw may land on a weekend. Our list of things to do after installing Ubuntu 26.04 server shows how to confirm they’re on, and the Ubuntu 26.04 hardening guide covers the settings worth checking. Recent check-and-patch posts on the Linux kernel TCP flaw, the nginx alias heap overflow and the BIND GSS-TSIG replay flaw follow the same pattern of version table, check, patch and proof. For CVE-2026-109518 our verdict is short. Patch Debian and Ubuntu now, and attach Ubuntu 20.04 and older machines to Ubuntu Pro to get the ESM fix (16.04 and 14.04 also need the Legacy add-on).