
Shell script that assesses Ubuntu kernel patch state for CVE-2026-98432 and applies a persistent nftables or iptables stopgap dropping IPv4 TCP packets carrying IP options.
# 1. Inspect the host; no changes.
sudo ./cve-2026-98432-mitigate.sh check
# 2. Get a patch-state verdict for the exact running kernel package.
sudo ./cve-2026-98432-mitigate.sh assess
# 3. Apply the stopgap filter and make it survive reboot.
sudo ./cve-2026-98432-mitigate.sh enable
# 4. Prove that normal TCP still works and IP-option TCP is dropped.
sudo ./cve-2026-98432-mitigate.sh verify
# 5. Monitor. Exit 0 = healthy, 1 = mismatch/persistence failure, 2 = no state.
sudo ./cve-2026-98432-mitigate.sh status
# 6. After booting a kernel that Ubuntu marks as fixed.
sudo ./cve-2026-98432-mitigate.sh disable
enable refuses to change the ruleset when CIPSO/NetLabel is detected, because the rule drops all TCP carrying IP options, including labelled traffic. Use --ignore-cipso only if you accept that trade-off. Containers or hosts without systemd should use --no-persist; otherwise enable exits 4 when reboot persistence cannot be established while keeping the active rule in place.
CVE-2026-98432 is a use-after-free in the Linux IPv4 TCP handshake. It is reachable when an incoming SYN carries IP options. The real fix is a patched kernel; this script is a stopgap that drops inbound IPv4 TCP packets whose IP header length is greater than 5 (IHL 6-15), i.e. packets carrying IP options, before conntrack and Docker NAT.
It supports two equivalent backends:
table ip cve_2026_98432, prerouting priority -310, TCP only, counter, drop.raw PREROUTING, u32 match 0>>24&0xf=6:15, TCP only, counter, drop.The nft shape uses the ip family and a numeric priority so it works on Ubuntu 16.04's nft 0.5 as well as current nft 1.x. The iptables shape works with iptables 1.6 and later. No package is installed unless --install-nft is passed.
The script validates the complete expected rule, not fragments. For nft it requires the pre chain to carry the prerouting hook at exactly priority -310 (or the legacy raw - 10 spelling) and the expected DROP to be the first rule. For iptables it requires iptables -C to succeed and the complete first raw PREROUTING rule to match after normalization. enable repairs a displaced rule instead of refusing to re-apply.
Akamai's script contributed the assessment and safety ideas below. Its enforcement shape was not adopted because ours is stricter and 16.04-compatible. The most important incorporated findings, in priority order:
assess resolves the running kernel's exact image package (linux-image-$KVER, then linux-image-unsigned-$KVER, then the owner of /boot/vmlinuz-$KVER). Metapackages such as linux-image-generic are shown as context only, never used as verdict evidence. A changelog hit is strong but fallible evidence; a missing changelog plus an independently conclusive clean upstream version at or above the fixed release still yields PATCHED; a vendor kernel without evidence yields UNKNOWN.enable exit 4 while keeping the rule active. status assesses persistence independently from the oneshot's runtime state and rejects enabled-runtime as non-persistent.detected refuses by default, unknown warns, not_detected proceeds. Missing netlabelctl does not prove CIPSO is absent.check distinguishes verified-usable, present-unverified, unusable and unknown; --backend nft evaluates nft even when iptables works.XDP_PASS still enters the kernel stack.-x) output where possible, and a legacy filter/INPUT rule from an earlier version is reported and removed after the raw replacement is loaded.The rule match and state-file format are backward compatible. You do not need to disable first; re-running enable with this version repairs the rule in place, installs the updated boot unit, and records the new persistence field. If an old state file has no persist= line, status infers persistence from the unit state instead of failing on the missing field.
Operational changes to know about:
enable now exits 4 when the rule is active but reboot persistence failed. Previously it could exit 0 in that case.check now returns 0 only for a verified usable backend, 1 for no usable backend, 4 for present-but-unverified, and 2 for usage.assess is new and returns 0/1/3/4 as documented below.enable unless --ignore-cipso is passed.enable so the new unit ordering and ExecStart are applied.Prepared: 2026-10-30 (updated 2026-10-31)
Ubuntu tracker checked: 2026-10-31 11:59 UTC (page last updated 2026-10-30). No fixed kernel has shipped yet.
Scope: Linux servers, primarily Ubuntu 16.04 (xenial), 22.04 (jammy), 24.04 (noble) and 26.04 (resolute), including Docker/BTCPay hosts.
Deliverable: cve-2026-98432-mitigate.sh in this directory.
Tested on: Ubuntu 16.04, 22.04, 24.04 and 26.04.
6.8.0-149.149), 22.04 (5.15.0-203.213), 26.04 (7.0.0-43.43) and 26.10 (7.3.0-10.10).From the Ubuntu description: