Skip to content
Witen field notes

CVE-2026-98432: protect your Linux servers before the kernel fix arrives

· Witen Labs · Security advisory

Updated : Anthropic showed the flaw can give a remote attacker root, Red Hat now rates it Important, and Go programs listen with multipath TCP by default. How to turn multipath TCP off, and why the IP options rule still matters.

What happened

CVE-2026-98432 is a use-after-free in the code Linux uses to accept new IPv4 TCP connections. Every server that accepts TCP connections over IPv4 runs that code before any application sees the connection, so a web server, mail server, or SSH daemon is exposed whatever software it runs.

  • What goes wrong: when a connection is accepted, the kernel hands the IP options from the client’s first packet to the new socket without copying them. A retransmitted first packet racing that hand-off can make the kernel use memory it has already freed.
  • How serious it is: Ubuntu rates it High with a CVSS score of 9.8, reachable over the network without authentication. Red Hat now rates it Important (8.1): harder to trigger, but a full compromise when it works. It first rated it Moderate, with the impact on availability only.
  • It gives root in the lab: on October 27, Anthropic reported that its Claude model wrote a working exploit that runs commands as root on Linux servers with a multipath TCP (MPTCP) listener, sent from a remote machine with no login. In their test it took 48 minutes to leak a kernel address and five more to run commands. Anthropic describes it as a lab result, not an attack seen in the wild.
  • Go servers have the setup it used: programs built with Go 1.24 or later listen with MPTCP on Linux by default. See Go programs and multipath TCP.
  • The hard part: the fix is in the upstream stable kernels, but Ubuntu and Red Hat have not shipped fixed packages yet.
  • The good news: the bug only happens when the client’s first packet carries IP options, a rarely used part of the IPv4 header that ordinary TCP traffic never sets. Drop TCP packets that carry IP options and the bug has nothing to work with.

Go programs and multipath TCP

Anthropic’s exploit reached the bug through an MPTCP listener, and Go 1.24 and later open one for every TCP listener on Linux by default. Go’s security team confirmed it on October 29. Web servers, reverse proxies, API gateways, and other services written in Go therefore have exactly the setup Anthropic attacked, without anyone choosing it.

To see which services listen with MPTCP, run:

ss -Mltn

Rows that start with mptcp are MPTCP listeners. On Ubuntu 26.04, a Go 1.26 server listening on port 8080 shows both:

Netid State  Recv-Q Send-Q Local Address:Port  Peer Address:Port
tcp   LISTEN 0      4096         0.0.0.0:8080       0.0.0.0:*
mptcp LISTEN 0      4096         0.0.0.0:8080       0.0.0.0:*

Turn MPTCP off for the whole server

Few servers need MPTCP, and programs that ask for it fall back to plain TCP when it is off. Go services keep working. One setting covers every program on the host, in any language:

sudo sysctl -w net.mptcp.enabled=0

Make it survive a reboot, which is exactly when you are most likely to boot a kernel you haven’t checked:

echo "net.mptcp.enabled = 0" | sudo tee /etc/sysctl.d/90-cve-2026-98432.conf
sudo sysctl --system

Then restart your services, or reboot. A listener opened before the change keeps its MPTCP socket until the program restarts. Run ss -Mltn again: no row should start with mptcp.

Containers don’t inherit it. Every container starts with its own network settings, and MPTCP is on in each. Set it per container with docker run --sysctl net.mptcp.enabled=0, or in Compose:

services:
  web:
    sysctls:
      net.mptcp.enabled: 0

Or turn it off for one Go program

Start the program with GODEBUG=multipathtcp=0 in front of it:

GODEBUG=multipathtcp=0 ./your-server

For a systemd service, add Environment=GODEBUG=multipathtcp=0 with systemctl edit, then restart it. To build it in, put godebug multipathtcp=0 in the program’s go.mod and rebuild. If the program already sets GODEBUG, add it to the list with a comma.

Why the IP options rule still matters

Go calls turning MPTCP off a fragile mitigation, and so do we. One MPTCP listener you missed, in a container or a service you didn’t restart, leaves the server exposed. And the bug is in how Linux accepts every IPv4 TCP connection, not in MPTCP: turning MPTCP off blocks the exploit Anthropic published, not the flaw.

The IP options rule covers both. The bug only fires when the client’s first packet carries IP options, so dropping those packets protects every listener, Go or not, MPTCP or not. Let Warden apply it or add it by hand, turn MPTCP off as well if you don’t use it, and install the fixed kernel when your distribution ships it.

Step 1: Is your kernel fixed?

Run uname -r to see the kernel you are running. An installed update does nothing until you reboot into it, and a server can boot an older kernel than the newest one installed (see Step 3).

Fixed kernels for CVE-2026-98432 as of October 30, 2026
Your systemStatusWhat to do
Ubuntu 26.04 LTSVulnerable. The fix is in progress for linux 7.0.0-43.43; no fixed package is published yet.Mitigate it now (Step 2). Install the fixed kernel and reboot once Ubuntu marks it released; the tracker’s 7.0.0-43 is still work in progress.
Ubuntu 24.04 LTS and other releasesVulnerable, fix in progress.Mitigate it now (Step 2). Watch Ubuntu’s CVE page for your kernel package.
RHEL, AlmaLinux, Rocky 8, 9, and 10Affected. Red Hat has not released a fixed kernel yet.Mitigate it now (Step 2). Watch Red Hat’s CVE page for the kernel update.
Upstream stable kernels (Gentoo, Arch, your own builds)Fixed 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.Update to at least the fixed release on your branch and reboot. On Gentoo, emerge gentoo-kernel-bin 6.18.56 or later.
Other distributionsCheck your vendor’s security tracker for CVE-2026-98432.Distribution kernels carry backported fixes, so compare package versions, not the upstream number.

If you use Ubuntu Livepatch or another live-patching service, check whether it covers CVE-2026-98432; until it says so, assume it doesn’t.

Step 2: Mitigate it with Warden

Warden 0.1.39 mitigates CVE-2026-98432 by itself. While the running kernel is affected, it drops IPv4 TCP packets that carry IP options, before connection tracking or the TCP stack sees them, and it removes the rule once a fixed kernel runs.

Install Warden or upgrade to 0.1.39. It’s free and needs no account. Then check it:

sudo warden mitigations

On a new install, Warden starts in observation mode, as the install guide recommends: it watches your logs and changes no firewall rules, so the mitigation waits and Warden says why:

mitigation CVE-2026-98432: unavailable
  affected (Ubuntu has not released a fixed 7.0.0 kernel yet), but Warden is in observation mode (backend = "null") and changes no firewall rules. To apply the mitigation, turn on firewall blocking: set backend = "nft" under [jail], run warden validate, and restart Warden (https://www.witenlabs.com/docs/warden#firewall). Or add the rule by hand (https://www.witenlabs.com/blog/linux-kernel-cve-2026-98432-tcp-ip-options#without-warden)

To apply it, turn on firewall blocking. That also turns on Warden’s bans, so keep a second session or console open and follow Turn on firewall blocking the first time:

# In /etc/witen/warden.toml, under [jail]:
backend = "nft"
sudo warden validate --config /etc/witen/warden.toml
sudo systemctl restart witen-warden
sudo warden mitigations
mitigation CVE-2026-98432: enforcing via nft
  Ubuntu has not released a fixed 7.0.0 kernel yet
  dropped 0 packets (0 bytes) from 0 senders

If you’d rather keep Warden in observation mode, add the rule by hand instead.

Added the manual rule from the first version of this advisory? Remove it once warden mitigations says enforcing: systemctl disable --now cve-2026-98432.service stops the unit and deletes its table, then delete the two files (without the unit, run nft delete table ip cve_2026_98432). Both rules drop the same packets and whichever runs first catches them, so while the manual rule stays, Warden counts nothing.

  • It decides from your running kernel. Every Ubuntu series until Ubuntu releases a fix, the RHEL family, and upstream kernels older than their branch’s fixed release get the rule; a fixed kernel doesn’t. A kernel Warden can’t judge keeps it.
  • It follows the vendors. From 0.1.40, Warden checks a signed feed that Witen updates from the Ubuntu, Red Hat, and kernel trackers. Only a fix the vendor has released counts, so a build named as “work in progress” never removes the rule.
  • It drops only TCP with IP options. Legitimate TCP doesn’t use them, and other traffic with options, such as IGMP, passes.
  • It works with nftables, iptables, and XDP. The rule lives in its own table or chain, apart from Warden’s bans and from ufw or firewalld, and stays in place while Warden restarts.
  • It shows you what it caught. warden mitigations, the Mitigations view in warden tui (key 0), and warden validate report the state and the packets dropped.
  • It counts senders and never bans them. These packets are dropped before any handshake, so the sender address is never verified and could be forged to frame someone else.
  • You decide. Set [mitigations] mode = "observe" in warden.toml to count without dropping, or "off" to turn it off.

It is a mitigation, not the fix: install the fixed kernel as soon as your distribution ships it.

Step 3: After you update

  • Reboot, then check uname -r. On one of our own servers the boot loader configuration named the old kernel by version, so the first reboot after installing the fix came back on the vulnerable kernel. Package managers don’t always update extlinux or a hand-written GRUB entry.
  • With Warden, nothing else to do: once the fixed kernel runs and the feed records the vendor’s release, warden mitigations says not needed and the rule is gone.
  • On Warden 0.1.39, upgrade to 0.1.40 before you install Ubuntu’s 7.0.0-43. 0.1.39 treats 7.0.0-43 as fixed because Ubuntu’s tracker named it, while still listing the fix as work in progress. 0.1.40 waits until Ubuntu releases the fix.
  • With the manual rule below, remove it once the running kernel is fixed: systemctl disable --now cve-2026-98432.service, then delete the two files. Leaving it in place does no harm.

Don’t want Warden, or can’t install it?

The same mitigation as a plain firewall rule. It drops IPv4 TCP packets with IP options before connection tracking or the TCP stack sees them, and nothing else. Other IPv4 traffic with options passes untouched. That matters: a first version of our own rule dropped every IPv4 packet with options, and the only packets it caught on our servers were 32 bytes long, the size of the IGMP membership reports that carry the Router Alert option by design.

nftables (Ubuntu, Debian, RHEL, Alma, Rocky)

Save this as /etc/cve-2026-98432.nft. It uses its own table, so it doesn’t touch rules managed by ufw, firewalld, or other tools, and loading it twice replaces the rule instead of adding a copy.

table ip cve_2026_98432
delete table ip cve_2026_98432
table ip cve_2026_98432 {
    chain prerouting {
        type filter hook prerouting priority raw; policy accept;
        ip hdrlength != 5 ip protocol tcp counter drop
    }
}

Check it, load it, and confirm it is in place:

nft -c -f /etc/cve-2026-98432.nft
nft -f /etc/cve-2026-98432.nft
nft list table ip cve_2026_98432

iptables (older systems, iptables-legacy)

iptables -t raw -I PREROUTING -p tcp -m u32 --u32 "0>>24&0x0F=6:15" -j DROP

The u32 match reads the IPv4 header length; values above 5 mean the packet carries options. iptables loads the iptable_raw and xt_u32 kernel modules when you add the rule. Most distribution kernels ship both; if iptables says the raw table does not exist, check with modinfo iptable_raw xt_u32.

Keep the rule after a reboot

A rule loaded by hand disappears at the next reboot, which is exactly when you are most likely to boot a kernel you haven’t checked. On systemd hosts, load the nftables file at boot with a small unit, /etc/systemd/system/cve-2026-98432.service:

[Unit]
Description=Drop TCP packets with IP options (CVE-2026-98432)
DefaultDependencies=no
Before=network-pre.target
Wants=network-pre.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/nft -f /etc/cve-2026-98432.nft
ExecStop=/usr/sbin/nft delete table ip cve_2026_98432

[Install]
WantedBy=sysinit.target

Then run systemctl daemon-reload and systemctl enable --now cve-2026-98432.service. For iptables, save the rule with your distribution’s usual method, such as netfilter-persistent save or /etc/sysconfig/iptables.

nft list table ip cve_2026_98432 shows how many packets the rule dropped. A nonzero count means something sent TCP with IP options, which is unusual.

Sources