HIGHSecurity · Linux kernel · LPE · Container escape · April 2026 CVE-2026-31431 · "Copy Fail" Updated 4 May

Copy Fail (CVE-2026-31431), Public PoC for Linux Kernel LPE Across Mainstream Distros Since 2017

By NewMaxx /April 29, 2026·updated May 4, 2026
Update, 4 May 2026, WSL2 affected · CISA KEV · in-the-wild testing

Three things have landed since this bulletin was first published. (1) Windows Subsystem for Linux 2 is vulnerable. A fully-updated WSL2 install (kernel 6.6.87.2-microsoft-standard-WSL2, WSL version 2.6.3.0) is exploitable by the unmodified Theori PoC, confirmed in issue #96 on Theori's repo and acknowledged by Microsoft in microsoft/WSL #40365. Microsoft has stated the patched WSL2 kernel will ship via Windows Update as part of the May 2026 Patch Tuesday rollout on May 12. Until then, wsl --update alone does not fix it; the kernel itself has to be updated, and the fix isn't in the channel yet. See the new WSL2 section below. (2) CISA KEV listing. CISA added CVE-2026-31431 to the Known Exploited Vulnerabilities catalog on May 1, 2026, citing evidence of active exploitation. The BOD 22-01 patch deadline for federal civilian agencies is May 15, 2026. (3) In-the-wild activity. Microsoft Defender reports observing preliminary exploitation testing and expects threat-actor activity to ramp over the following days. Sysdig and Sophos have published independent confirmations of reliable exploitation across major distributions and have shipped detection rules.

Today, Theori's Xint Code team publicly disclosed "Copy Fail", CVE-2026-31431, a Linux kernel local privilege-escalation flaw in the AF_ALG AEAD path. The disclosed chain combines authencesn, algif_aead, and splice() to produce a controlled 4-byte write into the page cache of a readable file, including the cached image of a setuid binary such as /usr/bin/su. Theori's public PoC is a 732-byte Python script that targets /usr/bin/su by default and was directly demonstrated against Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 10.1, and SUSE 16. The fix reverts the 2017 algif_aead in-place optimization through commit a664bf3d603d, some distributions have fixed kernels available now, but not all supported distro kernel lines are patched yet (Debian's tracker, for example, still lists trixie and trixie-security as vulnerable at time of writing). Check the specific vendor tracker for your running kernel package, not just the upstream version number. The PoC is already public on GitHub, and a second independent PoC plus a non-destructive detector have since been published by other researchers. The formal CVE record describes the kernel-side fix in dry implementation terms and assigns CVSS scores in the 5.5 to 7.8 band; Theori's disclosure demonstrates the weaponized impact and is the better operational severity reference. Treat any multi-tenant Linux host, Kubernetes node, self-hosted CI runner, or cloud-SaaS-running-user-code service as actively exposed until patched.

Why this is "patch now," not "patch this week"

The combination is unusually bad: multiple working public PoCs (the original Theori 732-byte /usr/bin/su variant plus a separately published /etc/passwd variant), no race window or version-specific tuning needed, and a primitive that crosses container boundaries because the page cache is shared by the host. Theori reports the same 732-byte Python PoC worked unmodified across its tested Ubuntu, Amazon Linux, RHEL, and SUSE systems, and argues that mainstream kernels built between the 2017 change and the patch are broadly in scope. Treat any multi-tenant Linux host, Kubernetes node, CI runner, or cloud-SaaS-running-user-code service as actively exposed until patched or the workaround is in place.

Affected and fixed versions
CVE-2026-31431 · "Copy Fail" Disclosed: 2026-04-29 by Theori (Xint Code) Reporter / discoverer: Theori / Xint Code Research Team; Theori credits researcher Taeyang Lee with the initial AF_ALG / page-cache insight. Reported to kernel security: 2026-03-23 Patch in mainline: 2026-04-01 PoC public on GitHub: theori-io/copy-fail-CVE-2026-31431 Affected: Upstream introduced the vulnerable behavior in the 4.14 era and fixed it in 6.18.22, 6.19.12, and 7.0. Older LTS and vendor kernels remain distribution-dependent until their maintainers backport the fix. Fixed in mainline: 6.18.22, 6.19.12, and 7.0 (revert commit a664bf3d603d). Stable kernel patch commits: fafe0fa2995a0f7073c1c358d7d3145bcc9aedd8 ce42ee423e58dffa5ec03524054c9d8bfd4f6237 a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5 Public scoring: Public scoring varies by vendor: some records emphasize local integrity impact and score in the Medium band, others score the practical LPE impact higher. Ubuntu lists CVSS 3.1 7.8 / High and describes the issue as trivial local privilege escalation. Theori characterizes the primitive as 100% reliable LPE with cross-container relevance.
The formal CVE and vendor records describe the kernel-side fix in relatively dry implementation terms, while Theori's disclosure demonstrates the weaponized impact: reliable local root from an unprivileged account, with container-escape implications. Treat the public exploit writeup as the better operational severity guide. Distro-specific patched kernel versions vary; check your distribution's security advisory for the exact patched package version.
Status snapshot, 29 April 2026

Confirmed by Theori (copy.fail): Copy Fail chains a logic flaw in authencesn, through AF_ALG and splice(), into a 4-byte page-cache write. The primitive lets an unprivileged local user modify the in-memory page cache backing of a setuid binary (default target: /usr/bin/su), so the next invocation of that binary executes attacker-controlled code as root. The change is not persistent across reboot; the resulting root shell is. Theori directly verified the exploit against Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 10.1, and SUSE 16.

Confirmed by kernel / CVE records: the resolved issue is in the AF_ALG AEAD path, specifically "crypto: algif_aead, Revert to operating out-of-place". The exploitability comes from the interaction among authencesn, algif_aead in-place handling, and splice()-fed page-cache pages. The CVE record lists patch activity touching crypto/af_alg.c, crypto/algif_aead.c, crypto/algif_skcipher.c, and include/crypto/if_alg.h; that is the scope of the patch series, not a claim that the bug exists in all four files. The mainline revert was committed April 1, 2026 and is shipping in stable kernels 6.18.22 and 6.19.12; distributions are backporting to their respective supported kernels.

Required: a local unprivileged user account on the target. No network access, no kernel debugging features, no pre-installed primitives. The kernel crypto API (AF_ALG) ships enabled in essentially every mainstream distro's default config, so the entire 2017-to-patch window is in play out of the box.

Not required: a kernel offset table, a race window, or a heap spray. Theori specifically calls Copy Fail a "straight-line logic flaw" rather than the typical Linux-LPE class.


Who needs to act first

Theori's own copy.fail page categorizes affected workloads by operational priority. Reproduced and lightly summarized:

Priority Workload class Practical risk
High Multi-tenant Linux hosts Shared dev boxes, shell-as-a-service, jump hosts, build servers, anywhere multiple users share a kernel. Any user becomes root.
High Kubernetes / container clusters The page cache is shared across the host. A pod with the right primitives compromises the node and crosses tenant boundaries.
High CI runners & build farms GitHub Actions self-hosted runners, GitLab runners, Jenkins agents, anything that executes untrusted PR code as a regular user on a shared kernel. A pull request becomes root on the runner.
High Cloud SaaS running user code Notebook hosts, agent sandboxes, serverless functions, any tenant-supplied container or script. Tenant becomes host root.
Medium Standard Linux servers Single-tenant production where only your team has shell access. Internal LPE; chains with a web RCE or stolen credential into full server compromise.
Medium WSL2 on developer workstations Microsoft's WSL2 kernel is vulnerable until the May 12 Patch Tuesday update. A malicious npm/pip dependency that lands code in WSL becomes root inside WSL, with read/write to the user's C:\ via /mnt/c. See the WSL2 section.
Lower Single-user laptops & workstations You're already the only user. The bug doesn't grant remote attackers access by itself, but any local code execution becomes root.

Categorization source: Theori's copy.fail "Should you patch first?" panel; WSL2 row added by the Bulletin based on the May 4 confirmation in microsoft/WSL #40365 and the practical chain through compromised npm/pip packages.


Am I affected?

Quick checks

The single highest-signal check is whether your kernel has the revert commit. On any host:

uname -r

Compare against your distribution's security advisory for the package version that includes a664bf3d603d (or equivalent backport).

Kernel version alone is not enough

For distro users, uname -r by itself is not a reliable affected/patched check. A distribution may backport the fix without changing to the upstream fixed kernel version, or may continue to list a newer-looking vendor kernel as vulnerable until its advisory says otherwise. Use the per-distro advisory or package-status tracker as the source of truth, not the upstream version number.

Specifically check:

Ubuntu · Red Hat · SUSE · Amazon Linux · Debian

To check whether the affected module is currently loaded:

lsmod | grep algif_aead

Most distros load algif_aead on demand when an application opens an AF_ALG socket; absence from lsmod output right now does not mean the bug is unreachable. The kernel will auto-load the module when requested unless you've explicitly blacklisted it (see the mitigation step below).

Non-destructive detector (third party)

A non-destructive detector script published by an independent researcher exercises the actual bug path against a sentinel file in a temp directory, never touching system binaries. It returns exit 0 if the system is patched (or algif_aead is unreachable) and exit 2 if the vulnerable scratch-write fires. This is a higher-signal check than version comparison alone: test_cve_2026_31431.py. Read the script before running it. The same repository also contains a working LPE; for defender purposes you only want the detector. As with any third-party tool, run it on a host you own or are explicitly authorized to assess.

Operational note: NSS caching

At least one of the publicly available LPE variants targets /etc/passwd in the page cache. Hosts running an NSS caching daemon (nscd, sssd, systemd-userdbd) may incidentally mask the corrupted page from getpwnam() lookups, which can blunt that specific exploit variant. This is not a mitigation, the underlying primitive is unaffected and other targets (e.g. setuid binaries in the page cache) work regardless. But it is worth knowing when modeling blast radius on a particular host.


Response, in priority order

  1. Patch the kernel. For each affected host, upgrade to your distribution's published kernel package that includes the revert. Reboot, this is a kernel patch, not a live patch by default (some vendors ship live patches; if you use one, follow vendor guidance for activation). Verify post-reboot with uname -r matching your distribution's advised patched version. Distro-specific patched kernel versions are not uniform; check the per-distro security tracker links above for the exact package version that contains the fix.
  2. If you can't patch immediately, blacklist algif_aead. Per Theori's mitigation guidance, this is a defensible workaround that does not affect dm-crypt / LUKS, kTLS, IPsec / XFRM, in-kernel TLS, OpenSSL / GnuTLS / NSS default builds, SSH, or kernel keyring crypto, all of those use the in-kernel crypto API directly and don't go through AF_ALG. The commands per copy.fail: echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
    rmmod algif_aead 2>/dev/null || true
  3. Identify legitimate AF_ALG users on your hosts before blacklisting at scale. Userspace that explicitly uses AF_ALG is uncommon, OpenSSL with the afalg engine explicitly enabled, some embedded crypto offload paths, and applications that bind aead / skcipher / hash sockets directly are the main cases. To check before blacklisting: lsof | grep AF_ALG  ·  ss -xa
  4. For untrusted workloads, block AF_ALG at the seccomp layer regardless of patch state. Containers, sandboxes, CI runners, anything that executes tenant-supplied code, should deny socket creation in the AF_ALG family via seccomp. Do not assume the runtime default blocks this path; verify the active seccomp profile, and for untrusted workloads enforce a profile that denies AF_ALG socket creation explicitly. For Docker / containerd: confirm which seccomp profile is in effect and audit it against your trust model. For Kubernetes: securityContext.seccompProfile.type=RuntimeDefault at the pod or namespace level is a starting point, not a guarantee.
  5. For self-hosted CI runners specifically. If you operate self-hosted GitHub Actions runners, GitLab runners, or Jenkins agents on shared kernel hosts, treat these as Tier-1 priority. A malicious pull request or scheduled job can reach the runner's user shell, run the public PoC, and root the host. Until patched: stop running external-PR jobs on shared self-hosted runners, isolate runners to single-tenant ephemeral VMs, or move the affected repos to ephemeral cloud-hosted runners (which the cloud provider patches centrally).
  6. For Kubernetes operators specifically. Patch the node kernel; the page cache is a property of the host kernel, so an unpatched pod on a patched node is safe, and a patched pod on an unpatched node is not. Drain and patch nodes in normal rolling fashion, but treat the kernel-update-required pool as urgent rather than opportunistic.
  7. Audit for post-exploitation indicators of compromise. The exploit primitive itself is a page-cache write that doesn't leave persistent on-disk artifacts (the page cache is in-memory and not committed back to the underlying file). On a system that was compromised, the on-disk setuid binary is unchanged, but the process that ran via the corrupted in-memory copy may have executed any post-exploitation. Indicators worth checking on any Tier-1-priority host that ran untrusted workloads in recent weeks: unexpected new accounts, unexpected SSH authorized keys for any account, unexpected setuid binaries anywhere outside standard package paths, suspicious cron / systemd timer entries, container runtime logs showing unusual AF_ALG socket creation by tenant-supplied code. Per Theori, the bug has been silently exploitable for nearly a decade. Theori is not asserting in-the-wild exploitation; the audit is ordinary diligence given the long exposure window and the public PoC.
  8. For shared multi-tenant hosts you operate as a service to customers, communicate. If you sell managed Linux services (managed CI, notebook hosting, managed K8s, function-as-a-service, JupyterHub), publish a brief operator note: which kernel versions you run, when patched kernels are deployed, what mitigation is in place in the interim. Customers running tenant code on your platform need this to do their own risk reviews.
For single-user laptops / workstations

This is Theori's "Lower" priority tier on bare-metal Linux installs. The bug doesn't help a remote attacker reach your laptop on its own; you're already the only user. The risk profile is post-exploitation step-up: if a piece of malware or browser-exploit landed code execution as your unprivileged user, Copy Fail turns that into root. Apply the kernel update from your distribution on the normal cycle. No need to scramble.

If you run WSL2 on Windows, this category does not apply to you, see the WSL2 section below. The supply-chain-attack chain into your dev environment changes the calculus, and the patch isn't yet in the WSL update channel.


WSL2 specifically (Windows developers, read this)

Windows Subsystem for Linux 2 ships with a Microsoft-built Linux kernel rather than the kernel from your chosen distribution. That kernel (6.6.87.2-microsoft-standard-WSL2 as of WSL 2.6.3.0) is built from a Linux source tree that includes the vulnerable algif_aead in-place path, and the unmodified Theori PoC produces a root shell on it. The Ubuntu-24.04, Debian, openSUSE, and other distro images running on top of WSL2 inherit that kernel, so the choice of distro inside WSL does not change your exposure. Microsoft has acknowledged the issue and announced that the patched WSL2 kernel will ship via Windows Update as part of the May 2026 Patch Tuesday rollout (May 12).

Why this matters for developers, even on a personal machine

The standard "I'm the only user, so an LPE doesn't change much" reasoning fails for WSL2 on a developer workstation in a way it doesn't fail for a bare-metal Linux laptop. Your WSL2 environment routinely runs npm install, pip install, and similar package-fetching commands, often against direct or transitive dependencies from the supply chain. The Bitwarden CLI, xinference, Checkmarx, and Lightning compromises in this Bulletin's recent series each delivered code execution as the developer's unprivileged user inside exactly such an environment. With Copy Fail, that unprivileged execution becomes root inside WSL2.

Root inside WSL2 is not the same as Administrator on Windows, but it is meaningful. Per the linked Theori repo issue, it gives the attacker read and write access to the user's Windows home directory and read access to the rest of C:\ via the /mnt/c mount, which is sufficient to steal SSH keys, GPG keys, browser profile data, cloud-CLI credentials in %USERPROFILE%\.aws / .azure / .config\gcloud, and to plant additional executable payloads inside user-writable directories. It also enables manipulation of the WSL environment itself, persistence inside the distro image, and tampering with developer tooling (Git config, shell rc files, language-toolchain hooks) that runs the next time you start a shell.

What to do, by priority

  1. Check whether you're affected. From a Windows command prompt or PowerShell: wsl --version  ·  wsl -- uname -r If uname -r reports 6.6.87.2-microsoft-standard-WSL2 or any earlier WSL2 kernel build, you are vulnerable. The patched kernel version will be published with Microsoft's May 12 Patch Tuesday advisory; verify against that on the day.
  2. Until the WSL2 kernel update lands, blacklist algif_aead inside each WSL distro you use. This is the same workaround as on bare-metal Linux, applied inside the WSL distro image. From a shell inside the distro: echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif.conf
    sudo rmmod algif_aead 2>/dev/null || true
    wsl --shutdown  # from a Windows prompt, then reopen WSL
    Reboot of the WSL VM is required for the modprobe blacklist to take effect on next module load. Repeat per distro if you run multiple.
  3. Be especially cautious about npm install, pip install, uv, poetry, and similar package fetches inside WSL2 until patched. The Bulletin's April supply-chain series is the active threat model here: a malicious dependency that lands code execution as your WSL user can chain Copy Fail into root inside WSL, then read and write through /mnt/c. If you regularly install dependencies from arbitrary repos for evaluation or testing, do that inside an ephemeral throwaway distro (wsl --install -d Ubuntu-Throwaway --no-launch or a Dev Container) rather than your main WSL environment until the patched kernel ships.
  4. On May 12, run wsl --update. Microsoft's stated delivery channel is Windows Update, with the WSL kernel package itself updateable through wsl --update. Re-run wsl -- uname -r afterward and confirm the kernel version matches Microsoft's May Patch Tuesday advisory. Restart WSL with wsl --shutdown before relying on the new kernel; running distros stay on the old kernel until the WSL VM is restarted.
  5. Audit credentials and secrets that lived in your Windows user profile during the exposure window if you suspect WSL-side compromise. If you ran any package install from an untrusted or compromised source between the public PoC drop (April 29) and applying the fix, the conservative posture is to rotate SSH keys, cloud CLI credentials, and any tokens cached in %USERPROFILE%\.config / .aws / .azure / .kube, and to review browser-profile integrity. This is not a claim you were compromised; it is ordinary diligence for the threat model.

How the bug works, at a high level

Per Theori's copy.fail summary: the issue is a logic flaw in the authencesn path inside the kernel's algif_aead module, the userspace front door for authenticated-encryption-with-associated-data operations via the AF_ALG socket family. A 2017 optimization (commit 72548b093ee3) made the AEAD code path operate "in-place" rather than out-of-place, allowing source and destination scatter-gather lists to share memory pages. In certain combinations that path, when chained with splice(), allowed the kernel to write a controlled 4-byte value into the page-cache page backing a readable file, including the cached image of a setuid binary such as /usr/bin/su.

The April 1 mainline fix is a near-complete revert of the 2017 commit: "there is no benefit in operating in-place in algif_aead since the source and destination come from different mappings." Once the kernel always copies out-of-place, the page-cache pages can no longer end up in a writable destination scatterlist, and the primitive is gone.

Theori's full technical writeup (linked in the sources) explains the chain in detail, including the exact field interactions that let the in-place handling be steered toward a page-cache target. I am deliberately not reproducing that level of detail here: the public PoC is already a complete weaponization, and a response guide doesn't need to recapitulate the chain to be useful.


What Copy Fail says about the rest of the Bulletin's recent set

The connection to the rest of this Bulletin's April series is direct. The Checkmarx, Bitwarden CLI, and xinference compromises were all about getting code execution as a regular user inside someone's CI/CD or developer environment. Until today, the next step from "attacker has user-level code execution on a CI runner" to "attacker has root on the runner host" still required a separate privilege-escalation primitive. Copy Fail is that primitive, broadly applicable across mainstream Linux kernels built between the 2017 change and the patch per Theori's reporting, with a 732-byte public PoC.

The right reading isn't "now the supply-chain attackers have a kernel exploit." It is: shared CI/CD kernels were already a concentration of risk; this disclosure makes that concentration legible, and the mitigation is the same one that was already correct, namely, don't run untrusted-code workloads on shared kernels with persistent state. Ephemeral single-tenant VMs per job, properly seccomp-restricted sandboxes, and prompt kernel patching are all on that path.

One additional note worth flagging in light of the GitHub RCE bulletin from yesterday: Copy Fail was found by Theori's Xint Code tooling in roughly an hour of scan time against the kernel crypto/ subsystem. CVE-2026-3854 was found by Wiz using AI-augmented reverse engineering of GitHub's compiled internal services. Two high-impact disclosures in two days, both from teams using AI-augmented code analysis, both targeting attack surfaces that have been audited many times before. The cost of finding latent bugs in well-audited code is dropping visibly. Patch posture matters more than it did six months ago, not less.

One-line takeaway

Patch the kernel now on any multi-tenant Linux host, Kubernetes node, self-hosted CI runner, or cloud-SaaS-running-user-code service. Until patched, blacklist the algif_aead module (echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf then rmmod algif_aead). For untrusted workloads, block AF_ALG via seccomp regardless of patch state. WSL2 users: blacklist algif_aead inside each distro now and run wsl --update on May 12 once Microsoft ships the patched kernel; treat npm install / pip install from untrusted sources as a credential exposure path through /mnt/c until then. CISA federal patch deadline: May 15. Single-user bare-metal laptops can patch on the normal security-update cycle.

All Bulletins ↑ Primary source: copy.fail (Theori) →