Your Go Services Grew an MPTCP Listener. The Kernel Bug That Turns It Into Remote Root Is Still Unpatched on Ubuntu and RHEL

CVE-2026-98432 is a high-severity use-after-free in the Linux kernel IPv4 TCP handshake. Anthropic demonstrated a remote root exploit against MPTCP listeners but kept the code private. Go 1.24+ silently creates those listeners by default. In Kubernetes and service-mesh environments the vulnerability sits in the node kernel, outside mesh controls. Open models plus GPU access now make reproduction attempts cheaper. Teams need a clear interim response while Ubuntu and RHEL ship fixes.

The Vulnerability in Brief

CVE-2026-98432 is a race condition in the Linux kernel’s IPv4 TCP handshake code that can produce a use-after-free. The faulty logic has been present since Linux 4.4. When a new connection completes, the kernel transfers the IP options associated with the pending request to the new socket without copying them. If that socket is destroyed while another CPU is still using the options to answer a resent connection request, the kernel reads memory it has already freed. IPv6 is not affected by this particular race. The kernel’s own CVE team rates the issue 9.8 on the CVSS scale, treating attack complexity as low. Some distributions initially scored it lower on the grounds that winning the race is difficult, although Red Hat has since aligned more closely with the higher assessment.

An upstream fix was applied in early October and backported to the maintained stable kernel branches. Debian, Oracle Linux (for its UEK kernels) and certain Amazon Linux and SUSE packages have shipped corrected kernels. As of early November 2026, Ubuntu’s supported releases (including recent LTS and cloud variants) and Red Hat Enterprise Linux 8, 9 and 10 still list the issue as vulnerable or work-in-progress, with no fixed packages released. RHEL 7 is unaffected because its kernel lacks the vulnerable code.

The demonstrated remote root exploit used a multipath TCP (MPTCP) listener as its entry point. Anthropic’s unreleased research model produced a two-stage attack that first leaked a kernel pointer to defeat KASLR and then abused the same use-after-free to overwrite a callback and run commands as root. Neither the CVE record nor the kernel fix mentions MPTCP; the link comes from the Anthropic write-up. The underlying bug exists in ordinary IPv4 TCP connection setup, so services that do not use MPTCP are not automatically safe. The MPTCP configuration simply provided a reliable path for the full root exploit that was shown.

The practical consequence is that any Linux host accepting IPv4 TCP connections remains exposed until its kernel is updated. The highest-priority surface for the attack that has already been proven is any process that opens an MPTCP listener. That is the detail that makes the default behaviour of recent Go runtimes immediately relevant.

Flowchart of CVE-2026-98432: MPTCP listeners lead to a demonstrated remote root path, plain TCP still has the use-after-free, interim disablement, then a patched node kernel
The demonstrated remote root path used an MPTCP listener. Disable that default while Ubuntu and RHEL still owe a kernel.

Why Go Services Are the Practical Exposure

As of Go 1.24 the standard library enables Multipath TCP by default for listeners on Linux whenever the kernel supports it. The change applies only to the server side. Dialers continue to use ordinary TCP unless explicitly configured otherwise. The result is that a conventional call such as `net.Listen("tcp", …)` creates an MPTCP listening socket without any MPTCP-related code appearing in the application. Most Go HTTP servers, gRPC services, reverse proxies and custom listeners built with Go 1.24 or later therefore expose exactly the configuration Anthropic’s model used to obtain remote root.

The default is controlled by the `multipathtcp` GODEBUG setting, which is set to listeners-only in Go 1.24. Operators can override it in two ways. Setting the environment variable `GODEBUG=multipathtcp=0` disables MPTCP for both listeners and dialers at runtime. Placing `godebug multipathtcp=0` in the main module’s `go.mod` file (or using a `//go:debug` directive) sets the same behaviour at build time. Explicit calls to `SetMultipathTCP` on a `ListenConfig` or `Dialer` override the GODEBUG value, so those sites must be audited separately. The Go security team has described programme-by-programme disabling as a fragile mitigation: a single remaining MPTCP listener is enough to reintroduce the demonstrated attack path, and the underlying kernel bug is not limited to MPTCP.

Detection is straightforward. The command `ss -Mltnp` (or `ss -lnMp`) lists MPTCP listeners together with the processes that own them. On a typical Go service the output shows both the ordinary TCP listener that tools such as `ss -tlnp` display and the corresponding MPTCP socket. After applying `GODEBUG=multipathtcp=0` and restarting the process, the MPTCP entry should disappear. System-wide, `sysctl net.mptcp.enabled=0` prevents new MPTCP sockets from being created, although existing listeners remain until their processes are restarted. These steps remove the configuration that has already been shown to be exploitable. They do not repair the use-after-free in the kernel, so they remain interim measures until a patched kernel is installed and the host is rebooted.

A Go gopher holding a socket that splits into multiple MPTCP paths connected by a red line to an open kernel padlock labelled CVE-2026-98432
Go 1.24+ opens MPTCP listeners by default. net.Listen("tcp") is enough.

The Exploit Is Private. The Map Is Not

Anthropic’s Frontier Red Team published a high-level account of a working remote root exploit for CVE-2026-98432 but withheld the exploit code, the precise kernel version and configuration used in testing, and any ready-to-run proof of concept. What appeared is a clear description of the successful path: an MPTCP listener as the entry point, repeated winning of the IPv4 TCP handshake race to leak a kernel pointer and defeat KASLR, followed by use of the same use-after-free to overwrite a callback pointer and execute an arbitrary shell command as root. The write-up noted that a failed race only aborts the individual connection attempt rather than crashing the system, allowing an attacker to retry indefinitely. In the reported laboratory run the address leak took roughly 48 minutes and command execution a further five.

That description is enough of a map for others to begin work. A few years ago turning such an account into a reliable remote root exploit required specialised kernel expertise and lengthy manual iteration. Today the same text can be supplied to capable open-weight models such as Qwen running on readily available GPU clusters. These models do not produce a finished exploit on the first attempt, yet they substantially reduce the cost of exploration, debugging and refinement. Multiple independent groups can now run that search in parallel, lowering the barrier that previously limited this class of work to a small number of researchers.

Public material so far has remained limited. Research toolkits have demonstrated the ability to trigger the race and obtain a memory leak, but none has claimed to reproduce the full KASLR bypass and root payload stages that Anthropic described. No in-the-wild exploitation has been reported and the issue does not appear in CISA’s Known Exploited Vulnerabilities catalogue. The realistic expectation is therefore not an immediate flood of public exploits, but a meaningfully shortened interval between the publication of the map and the appearance of independent working versions. For operators running Go services that still expose MPTCP listeners, that interval is the period in which interim mitigations matter most.

The Kubernetes and Service Mesh Reality

The vulnerability resides in the Linux kernel running on the node. It is triggered during the IPv4 TCP handshake, before any packet reaches a container, a sidecar or an application. Container images, pod security contexts and service-mesh configurations therefore cannot close the gap. A patched kernel on the node (followed by a reboot, or a vendor live patch where one exists) remains the definitive fix. Until that kernel is in place, every pod scheduled on the node inherits the exposure of the underlying host.

Many Kubernetes control-plane components, operators and custom controllers are written in Go. When those binaries are built with Go 1.24 or later they inherit the MPTCP listener default unless it has been explicitly disabled. Workloads written in recent Go behave the same way. Envoy, the data-plane proxy used by most service meshes, does not enable MPTCP by default. Its support is an explicit listener option that must be turned on in configuration. Consequently the mesh itself is rarely the source of the demonstrated attack surface, while the Go services that sit behind or beside the mesh frequently are.

Network policies, mutual TLS and sidecar interception operate after the kernel has already accepted and processed the TCP handshake. They cannot prevent a use-after-free that occurs inside that handshake. An attacker who can reach a listening port on the node can attempt the race regardless of whether the eventual traffic would have been encrypted or authorised by the mesh. The practical implication for platform teams is that mesh controls remain valuable for many other threats but do not substitute for node-kernel patching or for the interim step of removing MPTCP listeners from Go components. In environments that still run their own clusters on Ubuntu or RHEL, the node kernel timeline continues to be an operator responsibility.

Interim Actions While Waiting for the Kernel

The first practical step is an inventory. On each node run `ss -Mltnp` (or `ss -lnMp`) to list every MPTCP listener and the process that owns it. Cross-reference those processes with known Go binaries. For any Go service built with 1.24 or later, confirm whether the MPTCP default is still active by inspecting the environment or the `go.mod` file used at build time. This quickly separates the configuration Anthropic demonstrated from ordinary TCP listeners that remain subject only to the broader use-after-free.

Where a Go service can be restarted, disable the default. Set `GODEBUG=multipathtcp=0` in the process environment or add `godebug multipathtcp=0` to the main module’s `go.mod` and rebuild. After the restart, re-run the `ss` command to confirm the MPTCP socket has disappeared. On hosts where MPTCP is unused at all, `sysctl -w net.mptcp.enabled=0` prevents new MPTCP sockets from being created. Existing listeners continue until their processes are restarted, so the sysctl alone is not sufficient. These changes remove the demonstrated root path without waiting for a distribution kernel.

Additional hardening can reduce the chance of successful races while the unpatched kernel remains. Filtering incoming packets that carry IPv4 options (Record Route or Timestamp) at the host firewall or at a network edge limits one of the conditions the kernel CVE team used in its scoring. Monitoring for repeated failed handshakes or unexpected kernel log entries provides an early signal, although the attack is designed to avoid crashing the system. Where a vendor offers a live patch for the specific CVE, apply it. None of these measures repairs the use-after-free itself.

All of the steps above are interim. They shrink or remove the configuration that has already been shown to yield remote root, and they may complicate other exploitation attempts. They do not eliminate the underlying kernel bug. A single overlooked MPTCP listener, an explicit `SetMultipathTCP(true)` call, or a future refinement of the attack that no longer needs MPTCP can re-open exposure. The only durable remedy is a patched kernel installed and running on the node. Until Ubuntu and RHEL ship those packages, the inventory and disablement actions remain the highest-leverage controls available to operators.

What This Means for Platform Teams

CVE-2026-98432 supplies a concrete illustration of the residual responsibility that remains when an organisation runs its own Kubernetes clusters. Service-mesh policy, network controls and container hardening address many application-level threats, yet they leave the node kernel timeline in the operator’s hands. Ubuntu and RHEL have not yet released fixed packages for this issue, while Debian and certain other distributions have. Teams whose nodes are still on the former distributions therefore face a longer window of exposure than those whose base images or managed platforms already include the upstream fix. For banks, insurers and other regulated operators that standardise on Ubuntu or RHEL for compliance or support reasons, that window is an operational fact rather than an abstract risk.

The episode also highlights the cumulative effect of silent defaults in modern runtimes. Go’s decision to enable MPTCP on listeners was made for performance and future-proofing reasons and was documented. In practice it produced a widely deployed configuration that matched a demonstrated remote root path without any explicit request from application owners. Similar defaults exist in other stacks. Platform teams that treat language and runtime behaviour as an implementation detail inside the container can miss host-level exposure that only becomes visible once a kernel vulnerability is published. An inventory process that includes both the node kernel version and the effective socket options of long-running services reduces that surprise.

Finally, the combination of a public technical map and widely available open-weight models shortens the interval in which interim controls are sufficient. Organisations that have already moved node-kernel patching into a predictable cadence, or that consume kernels from distributions with faster security response, absorb this class of issue with less disruption. Those still waiting on Ubuntu or RHEL packages must treat the Go MPTCP default as an immediate, reversible control while the kernel update is prepared. The broader lesson is that commodity Kubernetes does not remove the need to own the host operating system lifecycle. It merely relocates the points at which that ownership becomes visible.

Conclusion and Next Steps

The priority order is unambiguous. A patched kernel on every node is the only measure that closes the use-after-free. Until Ubuntu and RHEL ship those packages, the highest-leverage interim control is the removal of MPTCP listeners from Go services and any other processes that open them. That step eliminates the configuration Anthropic’s model used to obtain remote root. It does not repair the kernel bug and it does not protect against every possible future refinement of the attack, yet it meaningfully reduces the surface that has already been proven.

Immediate checks are inexpensive. On each node, list MPTCP listeners with `ss -Mltnp`, identify any Go 1.24 or later binaries, and apply `GODEBUG=multipathtcp=0` (or the equivalent `godebug` directive) followed by a restart. Where MPTCP is unused, set `net.mptcp.enabled=0` and confirm that no listeners remain. Record the current kernel version and the distribution’s advisory status so the eventual package can be applied without further discovery work. These actions can be completed in hours on most fleets and buy time while the vendor kernels are prepared.

For teams that run Go workloads on Kubernetes, the episode is a reminder that node-kernel currency remains an operator responsibility even after a service mesh is in place. Mesh controls continue to matter for many other threats. They do not substitute for the kernel update or for the short-term removal of the demonstrated MPTCP surface. Organisations that treat the host operating system lifecycle as a first-class platform concern will absorb this class of issue with less disruption. Those that still regard it as an external dependency will continue to discover, after publication, that the window for quiet remediation has already narrowed. The practical next step is to run the inventory today and to place the Ubuntu and RHEL kernel packages on the critical path as soon as they appear.

References

The Hacker News, “Linux Kernel TCP Flaw With 9.8 CVSS Score Affects Ubuntu, Red Hat and Other Distributions”, 29 October 2026.

Anthropic Frontier Red Team research disclosure (referenced in multiple contemporaneous reports), 27 October 2026.

Go security team notice on golang-announce / oss-security regarding CVE-2026-98432 and MPTCP defaults, 29 October 2026.

Linux kernel CVE record for CVE-2026-98432 (kernel.org CNA).

Ubuntu CVE tracker and Red Hat CVE pages for CVE-2026-98432 (status as of early November 2026).

Distribution advisories from Debian, Oracle Linux, Amazon Linux and SUSE for fixed packages.