Local privilege escalation in the Linux kernel's crypto/algif_aead module. Any unprivileged local user can perform a controlled 4-byte write into the page cache of any readable file. Point that write at a setuid binary like /usr/bin/su and you have root. The PoC is 732 bytes of Python. The bug is deterministic, no race condition, no per-kernel offsets. It has been latent in the tree since 2017.
| Field | Value |
|---|---|
| CVE ID | CVE-2026-31431 |
| Nickname | CopyFail / Copy Fail |
| Product | Linux kernel (crypto/algif_aead) |
| Class | Local privilege escalation, page-cache write |
| CVSS 3.1 | 7.8 HIGH (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
| CWE | CWE-669 (Incorrect Resource Transfer Between Spheres) |
| Introduced | Kernel 4.14 (2017), commit 72548b093ee3 |
| Fixed | 6.18.22, 6.19.12, 7.0 |
| Disclosed | 2026-04-29 by Theori on oss-security |
| CISA KEV | Not listed as of 2026-04-30 |
- CVSS 3.1 base score 7.8 HIGH from kernel.org as CNA. NVD enrichment still pending. NVD
- SUSE rates it 5.8 (CVSS v4.0). The discrepancy is the v3 vs v4 framework, not disagreement on impact. SUSE
- Classified CWE-669 because the bug crosses a privilege sphere: data flows from a writable scratch buffer into the shared page cache, which is supposed to mirror on-disk state. NVD
- EPSS score under 1% as of disclosure, despite working public PoCs. Expect this to climb. Hacker News thread
Every mainline Linux kernel from 4.14 (Nov 2017) through unpatched 6.x and early 7.0-rc carries the bug. Nine years of distro builds inherit it: Ubuntu, RHEL, Debian, SUSE, Amazon Linux. oss-security disclosure
uname -r alone is unreliable for triage. Distros backport patches into kernels that keep an old version string. Always check distro changelogs against the CVE ID. Hacker News thread
Two flaws compose to make the exploit work:
- In-place AEAD optimization (2017). Commit
72548b093ee3taughtalgif_aead.cto setreq->src = req->dstand chain pages fromsplice()into the writable destination scatterlist viasg_chain(). Page-cache pages, including pages backing read-only files, end up in a position the crypto layer treats as scratch memory. Xint/Theori writeup - Authencesn does not clean up after itself.
crypto_authenc_esn_decrypt()writes 4 bytes (theseqno_lofield from attacker-controlled AAD) past the legitimate output boundary atdst[assoclen + cryptlen]to rearrange Extended Sequence Number bytes, then never restores them. GCM, CCM, and standard authenc clean up. authencesn does not. oss-security disclosure
Composition: splice delivers page-cache references into the crypto path; authencesn's scratch write lands on those pages. The HMAC verification fails and recvmsg() returns -EBADMSG, but the 4-byte page-cache write has already persisted. The page is never marked dirty, so on-disk checksums stay valid and traditional file integrity tools (AIDE, Tripwire, OSSEC) miss the corruption entirely. Bugcrowd writeup
- Attack chain: open an
AF_ALGsocket withauthencesn(hmac(sha256),cbc(aes)), splice a target setuid binary into it, position the splice offset so the 4-byte write lands on the chosen instruction, trigger decryption, then exec the corrupted cached binary. Theori PoC - Original PoC is 732 bytes of Python. C and Go ports exist. The exploit is simpler than Dirty Pipe (CVE-2022-0847): no race, no timing, no kernel offset leaks. tgies/copy-fail-c, badsectorlabs/copyfail-go
- Confirmed working on Ubuntu 24.04, Amazon Linux 2023, RHEL 10.1, SUSE 16. Theori PoC
- Practitioner gotchas in the wild: PoC requires Python 3.10+ for
os.splice; on earlier versions it fails silently and gives false negatives. WSL2 cannot be mitigated via modprobe (the module is built in). x86_64-only PoC; ARM needs rewritten shellcode. Slackware's non-world-readable SUID binaries are naturally protected. Hacker News thread
The upstream fix reverts the 2017 in-place optimization. Source and destination scatterlists are separated again, so page-cache pages never enter the writable crypto destination.
| Branch | Fixed Version | Commit |
|---|---|---|
| mainline | 7.0 | a664bf3d603d |
| stable 6.19.x | 6.19.12 | ce42ee423e58 |
| stable 6.18.x | 6.18.22 | fafe0fa2995a |
Tracked as GHSA-2274-3hgr-wxv6 on GitHub Security Advisories.
| Distro | Status | Tracker |
|---|---|---|
| Debian sid | Fixed in 6.19.14-1 | tracker |
| Debian bullseye/bookworm/trixie | Vulnerable, pending | tracker |
| Ubuntu 22.04 / 24.04 | High priority, patches rolling out (137+ pkg combos affected) | Ubuntu CVE |
| Red Hat | Advisory page live, details still rendering | RHEL CVE |
| Amazon Linux 2 / 2023 | Important, pending fix | AWS ALAS |
| SUSE / openSUSE | Affected, pending across product line | SUSE CVE |
Disable algif_aead outright. Most workloads never touch it: dm-crypt, LUKS, kTLS, IPsec, and SSH all use the kernel crypto API directly, not the AF_ALG userspace interface. oss-security disclosure
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aeadFor RHEL kernels where algif_aead is built in (=y in config) rather than a module, use the kernel boot parameter initcall_blacklist=algif_aead_init instead. Hacker News thread
For container hosts: seccomp filters that block socket(AF_ALG, ...) (family 38) cut off the attack surface for all containers in one go. SELinux policies in enforcing mode have been reported to block exploitation at the algif_aead socket-create step. ByteIota writeup
No published Sigma, YARA, Snort, or Suricata rules as of 2026-04-30. The attack is in-memory and never touches disk in a way that file-integrity tools can see, so signature work has to focus on syscall patterns. Sesame Disk detection guide
auditd:
-a always,exit -F arch=b64 -S socket -F a0=38 -F a1=5 -k af_alg_watch
-a always,exit -F arch=b64 -S splice -k splice_watch
These are inferred rules, not vendor-published. The signal is AF_ALG socket creation paired with a splice from a SUID binary by a non-root UID within a short window. Sesame Disk detection guide
Falco / eBPF: tracing socket(AF_ALG) plus splice() on /usr/bin/su-like targets is the cleanest detection. No public Falco rule yet. Sesame Disk security explainer
Vulnerability check on a host: Theori's repo includes test_cve_2026_31431.py (exit 0 if patched, 2 if vulnerable). A second checker is at rootsecdev/cve_2026_31431. Theori PoC
The page cache is shared host-wide, so a 4-byte write from a container lands in pages backing the host filesystem. Standard container isolation does not help. The default response for hosts that cannot patch immediately is to disable algif_aead on the host and add a seccomp profile blocking AF_ALG for all containers. ByteIota writeup
VM-isolated runtimes (Firecracker, Kata, gVisor) are out of reach because the kernel boundary is real, not just a namespace. Rootless Podman with user namespaces also blocks the easy path because the SUID target inside the user namespace has no real privilege on the host. ByteIota writeup
CISA published an ADP assessment on 2026-04-29 but the CVE is not in the Known Exploited Vulnerabilities catalog as of 2026-04-30. CISA KEV
| Date | Event |
|---|---|
| 2017 (kernel 4.14) | Bug introduced via commit 72548b093ee3 |
| 2026-03-23 | Reported to Linux kernel security team by Theori |
| 2026-03-25 | Patches proposed and reviewed |
| 2026-04-01 | Fix committed to mainline (commit a664bf3d603d) |
| 2026-04-22 | CVE-2026-31431 published |
| 2026-04-29 | Public disclosure on oss-security by Jan Schaumann |
| 2026-04-30 | Last NVD modification |
The Register coverage, oss-security disclosure
- The discoverer is the offensive-security firm Theori. Their AI scanner "Xint Code" found this in roughly one hour of automated review of the Linux
crypto/subsystem after Taeyang Lee gave it the operator hint thatsplice()plus page cache was an interesting attack surface. This is one of the cleanest public examples of an AI-assisted CVE in a hardened tree. Bugcrowd writeup - Conceptual cousin to Dirty Pipe (CVE-2022-0847) and Dirty Cow (CVE-2016-5195): all three are page-cache write primitives. CopyFail is simpler because there is no race window. Bugcrowd writeup
- The page-cache primitive is more powerful than the LPE framing suggests. Anything readable to the attacker is corruptible in the cache, including shared library code paths used by other UIDs. SUID is just the obvious target. Xint/Theori writeup
- NVD: CVE-2026-31431
- oss-security disclosure (Jan Schaumann)
- Theori / Xint canonical writeup
- Bugcrowd analysis
- ByteIota technical writeup
- The Register coverage
- GitHub Advisory GHSA-2274-3hgr-wxv6
- Mainline fix commit a664bf3d603d
- Theori PoC repo
- tgies C port
- badsectorlabs Go port
- rootsecdev vulnerability checker
- Debian Security Tracker
- Ubuntu CVE page
- Red Hat CVE page
- Amazon Linux ALAS
- SUSE CVE page
- CISA KEV catalog
- Hacker News discussion
- Sesame Disk detection guide
- Sesame Disk security explainer