CVE-2026-98432: how to block the Linux TCP bug until Ubuntu and Red Hat ship a kernel
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 scores it lower because the race is hard to win. However, 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 already have fixed kernels out (Amazon Linux 2023 only for its optional 6.12 and 6.18 kernels so far). Ubuntu and Red Hat haven’t yet. Ubuntu lists every supported release as “work in progress” and Red Hat’s fix is deferred, so for most Linux servers there’s no kernel to install today.
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 -c CVE-2026-98432 /usr/share/doc/linux-modules-$(uname -r)/changelog.Debian.gz
On RHEL, Rocky and Alma:
rpm -q --changelog kernel-core-$(uname -r) | grep -c CVE-2026-98432
Anything above 0 means the kernel you’re running has the fix. On Ubuntu and RHEL you’ll get 0 for now.
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.
RFF is free for your first 100 endpoints: getrff.com.
Sources
- 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
Comments
Comments use GitHub Discussions, so you'll need a GitHub account to post. Corrections are especially welcome.