ENGINEERING
← All posts · October 29, 2026 · By Brian Vitko
Update, November 4
Someone is scanning for it. Marcus Hutchins reported residential proxies and Russia-based VPNs scanning the internet on port 443 with MPTCP connections as of November 2, which his team suspects is aimed at this bug. His own scan found about 2.1 million servers that answer an MPTCP connection on 443, about 763,000 of which completed a TLS handshake over it. That counts servers with an MPTCP listener, not vulnerable kernels, and there’s still no public exploit and no report of the bug being used in attacks.
He also points at the same thing I found on my lab VM: anything built with Go 1.24 or later listens with MPTCP when the kernel allows it, Caddy included. If you run Caddy or another Go service on Ubuntu, run the ss -lnMp check below on it first.
Ubuntu’s fixed kernels are still only in -proposed. Ubuntu’s archive republished on the evening of November 4 without them (I checked at 19:43 UTC). In its own post, the Ubuntu Security Team says security updates are the only appropriate mitigation and advises against turning MPTCP off, since that only answers the one known exploit, which hasn’t been released. That’s in line with what I saw: turning it off doesn’t close a listener that’s already open (see below). The block rule drops the trigger itself, so it’s still what I’d run on Ubuntu servers until the kernel lands.
Update, November 3
Red Hat shipped fixed kernels on November 1 and now rates the bug Critical (9.8):
| RHEL | Advisory | Fixed kernel |
|---|---|---|
| 8.10 | RHSA-2026:93414 | 4.18.0-553.182.1.el8_10 |
| 9.8 | RHSA-2026:93412 | 5.14.0-687.64.1.el9_8 |
| 10.2 | RHSA-2026:93413 | 6.12.0-211.72.1.el10_2 |
My Rocky 9.8 VM already had 5.14.0-687.64.1.el9_8 on November 3. Install it with sudo dnf update kernel and reboot. The kernel doesn’t protect you until you’re running it.
Ubuntu’s fixed kernels are only in the -proposed testing pocket so far (26.04 7.0.0-43.43, 24.04 6.8.0-149.149, 22.04 5.15.0-203.213), with no release date. 20.04 and 18.04 have nothing yet. Keep the block rule below on your Ubuntu servers until the kernel reaches the normal updates.
If you checked an Ubuntu kernel by hand, check it again. The -proposed 26.04 kernel was built before the CVE number existed, so its changelog lists the fix only by its patch title, “ipv4: free inet_opt and ireq_opt after an RCU grace period”. Searching for CVE-2026-98432, the way this post first said to, calls it vulnerable. The commands below now look for both. The RFF check had the same blind spot, and it’s fixed too.
I tested both on my lab VMs. Details are at the end.
The bug
CVE-2026-98432 is a use-after-free in the Linux kernel’s IPv4 TCP handshake, and the kernel team scored it 9.8. Red Hat first scored it lower because the race is hard to win, then raised it to Critical. Anthropic’s red team reported that one of its AI models built a working exploit that gets a root shell with no credentials on a server with a multipath TCP (MPTCP) listener. Their write-up says it took about 48 minutes to get past KASLR and another 5 to get a shell. They haven’t released the exploit, and so far there are no reports of the bug being used in attacks.
The bug goes back to kernel 4.4. The upstream fix is in 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10 and 7.3, and Debian, Oracle Linux and SUSE had fixed kernels out first (Amazon Linux 2023 only for its optional 6.12 and 6.18 kernels). Red Hat followed on November 1. Ubuntu lists its supported releases as “work in progress”, with the fixed kernels in -proposed.
What triggers it
It’s triggered by a TCP connection request (the SYN) with an IPv4 Record Route or Timestamp option. The kernel keeps those options with the half-open connection, and once the connection is set up, it passes them to the new socket without making a copy. If another CPU is handling a retransmitted SYN for the same connection at that moment, it can read the options after they’ve been freed. IPv6 isn’t affected, because the kernel copies the options there.
Normal traffic doesn’t carry IPv4 options. RFC 7126 already recommends that routers and firewalls drop packets with Record Route or Timestamp options, so you can drop them on the server too without breaking anything.
Start with servers that have an MPTCP listener
Their exploit needs a server with an MPTCP listener. Anthropic hasn’t said why, and the CVE doesn’t mention MPTCP at all, so I wouldn’t call a server without one safe. It’s still where I’d look first.
I figured MPTCP listeners would be rare, but my own Ubuntu lab VM had one I never set up: step-ca, on port 9000. Since Go 1.24, servers written in Go listen with MPTCP by default on Linux whenever the kernel allows it, and Ubuntu 26.04 allows it out of the box (net.mptcp.enabled = 1). My Rocky 9.8 VM had it turned off.
Check one machine
Is the running kernel fixed. Check your distribution’s kernel changelog instead of the version number. Ubuntu and Red Hat backport fixes into their own kernels, so a kernel with an older-looking version can already have the fix. On Ubuntu:
zgrep -cE 'CVE-2026-98432|free inet_opt and ireq_opt' /usr/share/doc/linux-modules-$(uname -r)/changelog.Debian.gz
On RHEL, Rocky and Alma:
rpm -q --changelog kernel-core-$(uname -r) | grep -cE 'CVE-2026-98432|free inet_opt and ireq_opt'
Anything above 0 means the kernel you’re running has the fix. On RHEL that’s 0 until you install the November 1 kernel and reboot into it. On Ubuntu it’s 0 unless you’ve taken the kernel from -proposed.
MPTCP listeners.
sudo ss -lnMp
If it prints nothing, nothing is listening with MPTCP. On my Ubuntu VM it printed step-ca on *:9000.
You’ll also see sysctl -w net.mptcp.enabled=0 going around as a fix. It stops programs from opening new MPTCP sockets (Go programs fall back to plain TCP), but it doesn’t touch listeners that are already open. When I turned it off on my VM, step-ca kept listening with MPTCP, even though a new MPTCP socket was refused. If you go that way, restart whatever ss -lnMp lists and run it again to make sure it’s empty.
For Go services specifically, the Go team’s advice is GODEBUG=multipathtcp=0 (as an environment variable, or godebug multipathtcp=0 in go.mod if you build it yourself), which turns MPTCP off for that program. Canonical has already shipped that change in Pebble, and there’s an open proposal to turn MPTCP off by default in Go. And since nobody has confirmed that a server without an MPTCP listener is safe, block the trigger.
Block the trigger
This nftables rule drops any IPv4 TCP packet with IP options. Without options, an IPv4 header is always 20 bytes, which ip hdrlength reports as 5 (it counts 4-byte words). So ip hdrlength gt 5 only matches packets that have options. It runs at priority -300, before connection tracking:
sudo nft add table ip cve_2026_98432
sudo nft add chain ip cve_2026_98432 pre '{ type filter hook prerouting priority -300; }'
sudo nft add rule ip cve_2026_98432 pre meta l4proto tcp ip hdrlength gt 5 counter drop
The rule only drops packets, so it can’t open anything your firewall blocks, and it runs fine next to ufw and firewalld. IPv6, UDP and ICMP aren’t affected. If the server also routes traffic for other machines, TCP packets with IP options passing through it get dropped too. The one network where IP options are normal is a labeled network using CIPSO (SELinux or Smack NetLabel), so don’t add this rule there. As written it’s gone after a reboot (the RFF script below takes care of that).
How I tested it
On Linux you can put IP options on a normal TCP socket with setsockopt(IP_OPTIONS), and the kernel adds them to every packet it sends, the SYN included, which makes it easy to test. From my Rocky VM I connected to SSH on the Ubuntu VM twice, once plain and once with a Record Route option:
| Ubuntu VM | plain SYN | SYN with Record Route |
|---|---|---|
| without the rule | connected | connected |
| with the rule | connected | dropped (the rule’s counter went up) |
I did the same test the other way around, with the rule on Rocky (where firewalld is running), and got the same result. The rule was still there after firewall-cmd --reload and after a reboot.
That shows the trigger is blocked, but I didn’t run the exploit itself.
Doing this across a fleet
There are two new Linux entries in the RFF Script Library:
- TCP IP-options bug (CVE-2026-98432) - Exposure Check (Linux) checks the running kernel against the distribution’s changelog, and reports whether a fixed kernel is installed but not booted yet, whether the drop rule is loaded right now, which programs listen with MPTCP, and which IPv4 ports are open off loopback.
- Block CVE-2026-98432 (TCP IP options) (Linux) adds the rule and a systemd unit, so it comes back after every reboot or nftables restart. Then it checks the live ruleset to make sure the rule actually loaded. You can do a dry run first and undo it later.
Here’s the check on my Ubuntu VM before I ran the block:

Here’s the block itself:

And here’s the same check afterwards:

One thing I ran into on Rocky: my first version of the script wrote the rule file to /tmp and then moved it into /etc. mv keeps the file’s SELinux label, so nftables wasn’t allowed to read it and the rule never loaded at boot. If you write your own unit for this, create the file directly in /etc.
Once your distribution ships the fixed kernel, install it, reboot and run the check again. After that you can remove the rule.
Checking the fixed kernels (November 3)
On Rocky 9.8 the check said VULNERABLE on 5.14.0-687.56.1.el9_8. After dnf install kernel-5.14.0-687.64.1.el9_8, before the reboot, it said the fix was installed but not running:

And after the reboot:

On the Ubuntu 26.04 VM I turned on -proposed with a low pin, so nothing else upgrades from it, and installed only the kernel:
sudo tee /etc/apt/sources.list.d/ubuntu-proposed.sources <<'EOF'
Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: resolute-proposed
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
EOF
printf 'Package: *\nPin: release a=resolute-proposed\nPin-Priority: 100\n' | sudo tee /etc/apt/preferences.d/proposed-updates
sudo apt update
sudo apt install -t resolute-proposed linux-image-7.0.0-43-generic linux-modules-7.0.0-43-generic
This is where the first version of the check went wrong. It called 7.0.0-43 vulnerable, because the changelog has the fix under its patch title, not the CVE. With that fixed, it said “fixed, reboot needed” before the reboot, and fixed after it:

-proposed is Ubuntu’s testing pocket, and the Ubuntu Security Team’s advice is to wait for the security update. I’d only do this on a server where the block rule isn’t an option, and keep the rule everywhere else. On that VM I deleted both files again afterwards so nothing else comes from -proposed.
RFF is free for your first 100 endpoints: getrff.com.
Sources
- The Stack: CVE-2026-98432, fears mount over Linux kernel networking bug (November 4: Marcus Hutchins on the scanning, his MPTCP counts, Go and Caddy)
- Ubuntu: fixes available in -proposed for CVE-2026-98432 (the -proposed kernels, and the advice against turning MPTCP off)
- The Hacker News: Red Hat patches 9.8-rated Linux TCP RCE flaw while Ubuntu releases fixes for testing (November 3)
- Red Hat errata: RHSA-2026:93414 (RHEL 8), RHSA-2026:93412 (RHEL 9), RHSA-2026:93413 (RHEL 10), and the security bulletin RHSB-2026-016
- The Hacker News: Linux kernel TCP flaw with 9.8 CVSS score (vendor status, fixed versions, Anthropic’s exploit)
- Atlas: CVE-2026-98432 (the trigger options and the nftables rule)
- Ubuntu: CVE-2026-98432
- Red Hat: CVE-2026-98432
- Go 1.24 release notes (MPTCP by default for listeners)
- Go issue 82717: disable MPTCP by default (the
GODEBUG=multipathtcp=0advice) and Pebble PR 1146 - PatchMon: CVE-2026-98432 status (per-distribution status, exploit not published)
- typhoon1217/cve-2026-98432-mitigation (the same drop rule, independently tested, and the CIPSO caveat)
- RFC 7126: Recommendations on filtering of IPv4 packets containing IPv4 options