How a 732-byte script earned root on every major Linux distribution by corrupting files that never changed on disk
The file on disk was untouched. The checksum was clean. The file integrity monitor saw nothing. And yet, when a user ran /usr/bin/su, they handed an attacker a root shell. That is the core trick in Copy Fail: the attack modifies a file's in-memory copy without ever writing to disk, leaving every standard detection tool looking at evidence that says nothing happened.
The exploit is a 732-byte Python script. It uses only standard library functions available in Python 3.10 and above. It requires no compiled payloads, no knowledge of kernel memory addresses, no race condition timing, and no special privileges beyond a normal user account. The same unmodified script achieves root on Ubuntu 24.04, Amazon Linux 2023, Red Hat Enterprise Linux 8, 9, and 10, and SUSE 16. Within 24 hours of public disclosure on April 29, 2026, six independent reimplementations appeared on GitHub, including versions written in Go and Rust.
The detail that should concern anyone running Linux in a shared environment: this attack works across container boundaries. A process running inside a Docker container, a Kubernetes pod, or a CI/CD runner can corrupt the in-memory copy of a file on the host, then trigger that file's execution to escape the container entirely. Kubernetes Pod Security Standards Restricted profiles and RuntimeDefault seccomp policies, two of the most commonly cited container hardening controls, do not block it.
Narrative · 7 min read
The Context
Linux is the operating system running the overwhelming majority of the world's cloud infrastructure, container platforms, and server workloads. When a vulnerability allows any unprivileged user to become root on Linux, it is not a niche problem. It is a problem for essentially every organization that runs software in the cloud.
Copy Fail (CVE-2026-31431) affects every Linux distribution shipping kernel version 4.14 or newer, covering all mainstream Linux systems built since August 2017. CISA added it to the Known Exploited Vulnerabilities catalog on May 1, 2026, citing active exploitation in the wild, and gave federal agencies until May 15 to apply fixes.
The Attack, Phase by Phase
Phase 1: Nine Years of Silent Convergence
Copy Fail was created by three separate, reasonable engineering decisions made over nine years, none of which was wrong on its own.
In 2011, a cryptographic component called authencesn was added to support a specific IPsec standard. As part of its design, it wrote 4 bytes to a specific offset in the output buffer as scratch space during decryption. Fine on its own.
In 2015, Linux gained the AF_ALG socket interface, letting user programs request cryptographic operations. This added a way to pass file contents directly into the crypto subsystem via splice(), which hands over a reference to the file's in-memory page cache rather than copying the data. Page cache pages were on the read-only input side, so authencesn's scratch write landed safely in the output buffer. Still fine.
In August 2017, a performance optimization merged the input and output sides into a single buffer to avoid unnecessary memory copies. Unintended consequence: page cache pages delivered via splice() were now on the writable output side. authencesn's scratch write, which had always targeted the output buffer, now targeted the kernel's in-memory copy of the spliced file.
The bug was now active. It would remain undetected for nearly nine years.
Phase 2: The Write Primitive
An attacker with any standard user account opens an AF_ALG socket configured to use authencesn, then uses splice() to pass a target file—such as /usr/bin/su—into the socket's input. When they call recvmsg() to trigger decryption, authencesn performs its scratch write into the page cache copy of that file.
The attacker controls exactly which 4 bytes get overwritten and what value is written, by choosing the file offset, splice length, and the assoclen parameter. The ciphertext is fabricated, so the operation fails and recvmsg() returns EBADMSG. But the 4-byte write has already happened.
The kernel never marks the modified page as dirty. The on-disk file is completely unchanged. File integrity monitoring tools see a clean file. The modification exists only in memory, persisting until reboot or page eviction.
Phase 3: Root Escalation and Container Escape
With the in-memory version of a setuid-root binary modified, the attacker simply runs it. Because setuid binaries execute with root permissions regardless of who launches them, the injected code runs as root.
In containerized environments, the impact is wider. Linux containers share the host kernel's page cache. A process inside a Docker container, Kubernetes pod, or CI/CD runner can splice a host file into the AF_ALG socket and corrupt its page cache entry. When that file is next executed on the host or in another container on the same node, the corrupted version runs—a full container escape requiring no additional kernel exploit.
Testing on Talos and Amazon EKS clusters confirmed that non-root pods running under Kubernetes Pod Security Standards Restricted with RuntimeDefault seccomp profiles could still create AF_ALG sockets and perform the page cache write. The security policies most organizations treat as strong container hardening do not block this attack path.
Phase 4: Disclosure, Patch Race, and Active Exploitation
The upstream fix was merged April 1, 2026, giving distributions a four-week head start before public disclosure on April 29. AlmaLinux shipped patched kernels on disclosure day; other distributions followed within hours to days.
Within 24 hours of disclosure, six independent weaponized exploits appeared on GitHub. CISA added the vulnerability to the KEV catalog on May 1, citing active exploitation in the wild.
A widely circulated mitigation—blocking the algif_aead kernel module via modprobe.d—was found ineffective on Red Hat Enterprise Linux, AlmaLinux, Rocky Linux, and CloudLinux. On those distributions, algif_aead is compiled directly into the kernel, so the modprobe.d rule runs without error but changes nothing. The correct mitigation is a kernel boot parameter: initcall_blacklist=algif_aead_init.
What Made This Possible
No review process spans nine years. Each of the three kernel changes was reviewed and approved independently. The dangerous intersection only became visible in retrospect. The Linux kernel's security surface is an emergent property of how independent subsystems interact over time, not a property any single reviewer can evaluate.
Container isolation is not a kernel security boundary. The page cache is shared across all processes on a host, including across container namespace boundaries. Kubernetes security policies operate above the kernel and cannot prevent kernel-level memory sharing. Any architecture that treats "running in a container" as equivalent to "isolated from the host" is one kernel LPE away from full multi-tenant compromise.
The attack leaves no forensic trace by design. Because the kernel never marks the corrupted page as dirty, the on-disk file is never modified. File integrity monitoring, checksum verification, and audit logs all report a clean system. The only evidence is in memory, erased on reboot.
What Should Have Stopped This
- Kernel patching. The fix (mainline commit
a664bf3d603d) reverts the 2017 in-place optimization, restoring separate scatterlists so page cache pages never enter the writable output path. Patched versions: 6.18.22, 6.19.12, and 7.0. This is the only complete fix. - Correct mitigation for RHEL-family systems. Add
initcall_blacklist=algif_aead_initto kernel boot parameters viagrubby. This disables the AF_ALG AEAD interface without affectingdm-crypt/LUKS, IPsec, SSH, or OpenSSL. - MicroVM-based isolation. Environments using AWS Firecracker (Lambda, Fargate), Cloudflare Workers, or gVisor are not affected because each tenant gets a separate kernel. Shared-kernel container platforms cannot provide this guarantee regardless of policy configuration.
- Behavioral detection. Because the attack leaves no on-disk trace, detection must focus on runtime behavior: unexpected AF_ALG socket creation by non-privileged processes,
splice()calls targeting setuid binaries, or privilege escalation followingEBADMSGerrors. Exposure can be assessed immediately withlsof | grep AF_ALG.
The Takeaway
Copy Fail is the same class of failure as the Stryker Intune wipe: a trusted system component weaponized against the organization it was built to protect. The shared failure: the attack operates entirely within the normal behavior of a legitimate subsystem, so controls monitoring for anomalous activity see nothing.
Three correct engineering decisions, made by different people over nine years, combined to create a root exploit. No single reviewer was wrong. No single change was negligent. The vulnerability was an emergent property of the system, invisible to any review process that evaluated changes in isolation.
The discovery method adds a new dimension. Xint Code's AI-assisted analysis surfaced this vulnerability in approximately one hour of automated scan time against the Linux kernel's crypto subsystem. The economic assumption underpinning patch prioritization—that kernel-grade zero-days are expensive to find and therefore rare—is no longer reliable.
Pattern to remember: A kernel subsystem that modifies memory it does not own can be weaponized to corrupt any file the attacker can name, without leaving any on-disk evidence.
What changed: The cost of finding a universal, reliable Linux root exploit dropped from months of expert research to one hour of automated scan time against a single subsystem, meaning the supply of critical kernel vulnerabilities is no longer bounded by the number of humans capable of finding them.
Technical Deep Dive · 4 min
The Technical Mechanism
CVE-2026-31431 is a write-what-where primitive in the Linux kernel's algif_aead module, the AEAD (Authenticated Encryption with Associated Data) socket interface of the kernel's userspace cryptographic API (AF_ALG). The vulnerability arises from the interaction of three kernel changes across nine years.
Root cause: authencesn scratch write (2011). The authencesn cryptographic template (commit a5079d084f8b) implements combined authentication and encryption for IPsec Extended Sequence Numbers per RFC 4303. During decryption, authencesn writes 4 bytes at offset dst[assoclen + cryptlen] to temporarily rearrange the seqno_lo field for HMAC computation. This write uses scatterwalk_map_and_copy() and targets whatever scatterlist is designated as the destination. The original content at that offset is never restored.
Attack surface: AF_ALG splice() path (2015). algif_aead.c introduced a splice() path that delivers page cache pages into the crypto scatterlist by reference rather than by copy. At introduction, AF_ALG used out-of-place operation (req->src != req->dst), so spliced pages remained in the read-only source scatterlist and authencesn's scratch write targeted the user's output buffer.
Vulnerability activation: in-place optimization (August 2017, commit 72548b093ee3). The optimization copied AAD and ciphertext from the transmit scatterlist into the receive buffer, then chained authentication tag pages by reference using sg_chain(), and set req->src = req->dst. This placed page cache pages from splice() directly into the writable destination scatterlist. authencesn's scratch write at dst[assoclen + cryptlen] now walked via scatterwalk_map_and_copy() into those chained page cache pages, writing the 4-byte seqno_lo value from the sendmsg AAD directly into the kernel's cached copy of the spliced file.
Exploit primitive. The attacker controls the write target (via splice file offset and assoclen) and the write value (via seqno_lo in the AAD). The HMAC computation fails because the ciphertext is fabricated, and recvmsg() returns EBADMSG, but the write has already committed. The kernel never sets the PG_dirty flag on the modified page, so writeback never occurs and the on-disk file is unchanged. No other standard AEAD algorithm (GCM, CCM, authenc) writes past the output boundary.
Exploit chain. Four syscalls: socket(AF_ALG, SOCK_SEQPACKET, 0), setsockopt() to bind authencesn(hmac(sha256),cbc(aes)), splice() to deliver the target file (e.g., /usr/bin/su) via pipe into the socket, and recvmsg() to trigger the operation. The 732-byte Python proof-of-concept requires Python 3.10+ for os.splice, uses no compiled payloads, no kernel offsets, and no race conditions. It achieves root on Ubuntu 24.04, Amazon Linux 2023, RHEL 10.1, and SUSE 16 without modification.
Fix. Mainline commit a664bf3d603d (Herbert Xu, April 1, 2026) reverts the 2017 in-place optimization, restoring out-of-place AEAD operation and keeping page cache pages out of writable scatterlists. Patched kernel versions: 6.18.22, 6.19.12, 7.0.
CVE and Advisories
- CVE-2026-31431: CVSS 7.8 (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H). CWE-787 (Out-of-bounds Write). Assigned by the Linux CNA on April 22, 2026.
- CERT-EU Advisory 2026-005: Published April 30, 2026. Recommends prioritizing Kubernetes nodes and CI/CD runners.
- CloudLinux Mitigation Advisory: Published April 30, 2026. Documents failure of
modprobe.dworkaround on RHEL-family kernels and correctinitcall_blacklistapproach. - AlmaLinux Patch Advisory: Published May 1, 2026. Patched kernels moved to production repositories at 21:07 UTC.
- CISA KEV listing: Added May 1, 2026. FCEB remediation deadline: May 15, 2026.
MITRE ATT&CK Mapping
| Technique ID | ATT&CK name | How it appeared |
|---|---|---|
| T1068 | Exploitation for Privilege Escalation | Exploits algif_aead write primitive to escalate from unprivileged user to root via corrupted setuid binary. |
| T1611 | Escape to Host | Page cache shared across container namespace boundaries enables container escape without additional exploit. |
| T1565.001 | Stored Data Manipulation | Modifies kernel page cache copy of target binary; on-disk file unchanged, bypassing integrity monitoring. |
| T1562.001 | Impair Defenses: Disable or Modify Tools | In-memory-only modification evades file integrity monitoring, checksum verification, and audit logging. |
| T1059 | Command and Scripting Interpreter | Exploit delivered as a 732-byte Python script using only standard library modules. |
Indicators of Compromise
Detection is structurally difficult because the attack leaves no on-disk forensic trace. The modified page cache is erased on reboot. Standard indicators (file hash changes, audit log entries for file writes, integrity monitoring alerts) will not fire.
Runtime Indicators
AF_ALGsocket creation by non-privileged processes:lsof | grep AF_ALGorss -a | grep algsplice()syscalls targeting setuid binaries from non-root processes (requiresauditdrules onsplicewith path filtering)EBADMSGerrors in kernel logs (dmesg) correlated with subsequent privilege escalation events- Unexpected root shell spawns from setuid binaries (
/usr/bin/su,sudo,pkexec) without corresponding authentication events
Container-Specific Indicators
- AF_ALG socket creation from within container namespaces (visible in host-level
auditdwith namespace context) - Cross-pod page cache corruption: two pods from the same image on the same node observing different file contents for the same path
No network indicators exist. The attack is entirely local.
Attribution
No nation-state actor or criminal threat group has been attributed to discovery or weaponization of CVE-2026-31431. The vulnerability was discovered by Taeyang Lee at Theori through prior kernelCTF work, with the full exploit chain developed by the Xint Code Research Team using their AI-assisted source code analysis platform. The platform surfaced the vulnerability in approximately one hour of automated scan time against the Linux kernel's crypto/ subsystem with one operator prompt and no manual harnessing. The same scan surfaced additional high-severity bugs still in coordinated disclosure as of April 29, 2026. CISA's KEV listing cites evidence of active exploitation in the wild, and Microsoft Defender observed preliminary testing activity post-disclosure, but no specific threat actor has been named by any threat intelligence firm.
Primary Sources
- 01.Copy Fail: 732 Bytes to Root on Every Major Linux Distribution
Xint (Theori) · April 29, 2026
- 02.CVE-2026-31431: Copy Fail vulnerability enables Linux root privilege escalation across cloud environments
Microsoft Security Blog · May 1, 2026
- 03.CERT-EU High Vulnerability in the Linux Kernel (Copy Fail)
CERT-EU · April 30, 2026
- 04.CISA Adds Actively Exploited Linux Root Access Bug CVE-2026-31431 to KEV
The Hacker News · May 2, 2026
- 05.CVE-2026-31431 (Copy Fail): Mitigation and Upcoming Patches for CloudLinux
CloudLinux · April 30, 2026
- 06.Copy Fail (CVE-2026-31431) Patches Released
AlmaLinux · May 1, 2026
- 07.What we know about Copy Fail (CVE-2026-31431)
Bugcrowd · April 30, 2026
- 08.Copy Fail in Kubernetes: RuntimeDefault Did Not Block AF_ALG
Juliet · May 2, 2026