21 min read
By

CVE-2026-31431 "Copy Fail" — why the kernel matters

29 April 2026. Trivial local privilege escalation in the Linux kernel via the AF_ALG crypto subsystem (CVE-2026-31431, “Copy Fail”). Public PoC, cross-distribution, mitigation belongs on the host. What we deployed for our managed hosting customers — and which follow-up LPEs (Dirty Frag, Fragnesia) sit on this line.

Mattschwarzer DDR5-RAM-Riegel liegt diagonal auf dunkler Schieferoberfläche, von links kühl beleuchtet, mit sichtbaren goldenen Kontakten und kurzem Schatten nach rechts.

TL;DR — the 90-second summary

Affected?

Linux kernel 5.10 LTS through 6.6 LTS in practically all mainstream distributions — Debian, Ubuntu, RHEL, SUSE, Amazon Linux. All container hosts as well, regardless of the container distribution.

Risk?

Local privilege escalation to root via the AF_ALG crypto subsystem. Public PoC available, trivially reproducible.

Immediate action?

Where the kernel patch hasn't been deployed yet: disable algif_aead via modprobe blacklist and restrict crypto_user access. Then verify against the PoC.

Recommendation?

German Mittelstand: deploy the distribution patch, schedule a reboot. Enterprise/Kubernetes: additionally enable detection hooks (eBPF/Tetragon) on crypto-user syscalls.

Criticality?

High (see badge in the page header).

 

CVE-2026-31431 is a pure kernel vulnerability. It sits in the Linux kernel's crypto subsystem, specifically in the AF_ALG interface and the handling of certain memory operations around algif_aead. The public proof-of-concept fits on a sheet of A4 paper and needs no exotic preconditions. It uses standard kernel functionality that's active on practically every Linux system, and it works cross-distribution.

The detailed technical write-up is at copy.fail. Important for framing: this is a local privilege escalation. An attacker first needs code execution as an unprivileged user on the host. Once that's given, the exploit escalates reliably to root.

A common mistake in framing is: „if the container is secure, the system is secure.“ That's true for many classes of vulnerabilities. For kernel issues, it isn't. Containers, whether based on Debian, Alpine, or Wolfi, don't ship their own kernel. They use the host system's kernel. As soon as a process inside the container addresses the kernel and escalates there, isolation is bypassed.

Who is affected?

The vulnerability is cross-distribution. What matters is not the userland but the host kernel. Container images from Debian, Alpine, Ubuntu or Wolfi are equally affected because none of them ships its own kernel.

ComponentStatusCondition
Linux kernel 5.10 LTS through 6.6 LTSAffectedCONFIG_CRYPTO_USER_API_AEAD enabled (default on mainstream distros)
Linux kernel 6.7+ConditionalAffected before the distribution backport date, patched afterwards
Debian 11/12, Ubuntu 22.04/24.04AffectedUntil the patch from 1–7 May 2026
RHEL 8/9, Rocky, AlmaLinuxAffectedUntil the distribution errata release
Amazon Linux 2/2023AffectedUntil ALAS advisory; Bottlerocket separate
Container images (Debian/Alpine/Wolfi)Not affectedUserland without its own kernel; the host decides
Kubernetes worker nodesAffectedIf the host kernel isn't patched; every pod is an entry vector
Managed Kubernetes (EKS/AKS/GKE)Provider-dependentWorker image refresh is decisive
CI/CD runners (self-hosted)Highly affectedMulti-tenant workload density increases the exploitation path
WSL2 kernelAffectedUntil the Microsoft kernel update

The vulnerability is particularly critical where many workloads share the same kernel: container hosts with multi-tenant setups, self-hosted Kubernetes workers, and CI/CD runners. For exactly this class of risk, we schedule AI security audits into every release.

Impact

Copy Fail is a local privilege escalation (LPE). The CVSS rating sits in the high range per the NVD preliminary score (7.8 Local Attack Vector, low complexity, no user interaction). RCE or remote escalation isn't directly possible; the exploit requires existing code execution in user space.

What that means in practice:

On the business side: downtime due to reboot is the most likely direct impact. Data loss is not a realistic scenario with clean mitigation; the reputational question only arises if an incident occurs before the patch.

Copy Fail in Kubernetes — the second class of threat

On a single Linux VM, Copy Fail is a local privilege escalation. In Kubernetes the same vulnerability manifests differently: not as escalation to root, but as lateral movement between pods — without container escape, without root, without capabilities. Anyone running K8s should keep both pictures in mind.

The operational mechanics emerge from the combination of two Kubernetes properties that look harmless in isolation. First: container images are built in layers, and identical base layers are stored only once physically on a node (OverlayFS). Second: when the Linux kernel reads a file from disk, it keeps a copy in the page cache. The page cache is a node-wide resource and is not isolated per container. It's keyed by (filesystem device, inode). Two pods from the same base layer that execute /usr/bin/cat read from the same page cache entry.

This is exactly where Copy Fail strikes in K8s. An unprivileged process in a pod opens a file read-only, corrupts its page cache copy via the AF_ALG path, and waits. The next pod that executes the same file runs against the manipulated content — without anything ever being written to disk. The attacker never enters the host and sees nothing from the outside: they pick a common binary blindly (cat, bash, a shared library), corrupt it, and let Kubernetes decide which pod touches it next.

The trigger is Kubernetes itself. Liveness and readiness probes are the standard mechanism by which K8s periodically runs into pods, typically every few seconds. Stream Security validated the end-to-end flow on a production EKS cluster (Kubernetes 1.35, kernel 6.12.77, Amazon Linux 2023): between exploit launch in an unprivileged pod without a service account and code execution in a cluster-admin pod, less than ten seconds elapsed, triggered by a liveness probe executing cat /tmp/healthcheck.

The host stayed unaffected in that test. Its /usr/bin/cat sits on a different filesystem with a different inode, and the page cache cleanly separates the two entries. That means: Copy Fail in K8s is not a container-to-host escape, but container-to-container movement across the shared node layer. That doesn't make it less serious, it makes it structurally different. Network policies, RBAC, and file integrity monitoring don't see the attack because neither the network nor the persistent filesystem is touched.

The blast radius depends on your base image hygiene:

SetupRiskReason
All workloads share the same base (e.g. ubuntu:24.04)HighEvery compromised pod reaches every other pod on the same node
Mix with partial overlapMediumBlast radius limited to pods sharing layers
Every workload uses its own distroless or scratch imageLowNo shared layers, no shared page cache entry
Privileged DaemonSets (CNI, logging, monitoring) share base with application workloadsCriticalAttacker reaches pods with cluster-admin or host-network privileges

The painful consequence from Stream Security's demo: the attacker doesn't decide who gets hit. The Kubernetes scheduler, image layer sharing, and probe configuration do. Anyone who builds cluster-admin DaemonSets from the same base layer as unprivileged application pods has paved a path that their own platform conventions make trafficable.

Wolfi OS and the question of responsibility

At Moselwal we use Wolfi OS as our container base. For a vulnerability like Copy Fail, the clean framing matters — otherwise the question „is our container distribution to blame?“ gets answered wrong.

Wolfi is an undistro: pure userland without its own kernel. Wolfi uses the host system's kernel in full. Two things follow at the same time: Wolfi is not the cause of Copy Fail, and Wolfi cannot fix it either. Responsibility sits entirely on the host layer. The same applies 1:1 to distroless images, Chainguard images, Alpine, Debian-slim and any other lean container base: none of them ships its own kernel.

This is exactly why we stepped away from compose.yaml as a matter of principle a few weeks ago and built our container topologies declaratively. When the layers are cleanly separated — image, pod spec, host kernel — responsibility can be pinned per incident. In the case of Copy Fail: the host kernel. Image rebuilds would be busywork and would only blur the validation of the actual mitigation.

If you do run Wolfi images, you benefit indirectly: the slimmer userland attack surface reduces the chance that an attacker even reaches the point of launching a local kernel exploit. But that's defense in depth, not mitigation.

Mitigation and immediate actions

The short answer: deploy the distribution patch and reboot. Where a reboot isn't immediately possible, disable algif_aead via module blacklist and restrict crypto-user access. Both workarounds take effect at runtime.

Deploy the patch

 

# Debian/Ubuntu
sudo apt update && sudo apt upgrade -y linux-image-generic
sudo reboot

# RHEL/Rocky/AlmaLinux
sudo dnf upgrade -y kernel
sudo reboot

# SUSE
sudo zypper patch --category security
sudo reboot

 

NixOS — declarative patch and module blacklist

NixOS hosts patch differently: the kernel and the module blacklist are declared in /etc/nixos/configuration.nix, then nixos-rebuild switch pulls both in one step. Advantage: the next generation can be rolled back via the bootloader if the mitigation breaks a productive function.

 

# /etc/nixos/configuration.nix
boot.kernelPackages = pkgs.linuxPackages_6_6;  # patched LTS channel update
boot.blacklistedKernelModules = [ "algif_aead" ];
boot.kernel.sysctl = {
  "kernel.crypto_user_api" = 0;
};

# afterwards
sudo nixos-rebuild switch
sudo reboot

 

If you don't want to bump the kernel channel right away, declare only the module blacklist and the sysctl as a stopgap, and pull the channel bump in the next maintenance window. The declarative form makes both steps audit-proof and automatically reproducible.

Workaround without reboot: disable algif_aead

 

# Unload the module live (immediate effect)
sudo modprobe -r algif_aead

# Persistent blacklist
echo "blacklist algif_aead" | sudo tee /etc/modprobe.d/cve-2026-31431.conf
sudo depmod -a

 

Restrict crypto_user access

 

# sysctl stopgap: block the crypto user API for unprivileged processes
echo "kernel.crypto_user_api = 0" | sudo tee /etc/sysctl.d/99-cve-2026-31431.conf
sudo sysctl --system

 

Kubernetes: tighten the PodSecurity profile

 

apiVersion: v1
kind: Pod
metadata:
  name: hardened-workload
spec:
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: registry.example.com/app:1.0.0
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]

 

Kubernetes: base image hygiene and seccomp block

If you want to structurally minimize the K8s-specific lateral movement risk (see „Copy Fail in Kubernetes“ above), you have three levers beyond the kernel patch:

At the pod level, a seccomp profile blocks the entry point at the syscall. The RuntimeDefault profile from Docker and Kubernetes lets AF_ALG sockets through, the block has to be set explicitly:

 

{
  "defaultAction": "SCMP_ACT_ALLOW",
  "syscalls": [
    {
      "names": ["socket"],
      "action": "SCMP_ACT_ERRNO",
      "args": [
        { "index": 0, "value": 38, "op": "SCMP_CMP_EQ" }
      ]
    }
  ]
}

 

Rollback. The module blacklist can be reverted with sudo rm /etc/modprobe.d/cve-2026-31431.conf and a reload. Applications that use AEAD crypto in user space via AF_ALG (rare, mostly special VPN tools or crypto benchmarks) won't work without the module.

Technical deep dive

The exploitable path sits in the kernel's crypto subsystem. AF_ALG is a socket family that lets userspace processes address kernel crypto implementations, historically introduced for IPsec daemon implementations and hardware-accelerated crypto. The algif_aead module implements AEAD cipher operations (Authenticated Encryption with Associated Data) over this interface.

The vulnerability emerges in the handling of certain recvmsg() paths combined with incorrect reference counting on skb structures. Under specific race conditions, the kernel writes into a buffer that has already been freed — a classic Use-After-Free in the kernel heap. With controlled heap allocation, the freed slot can be occupied by an attacker-controlled data structure, which leads to kernel memory disclosure and ultimately privilege escalation via cred structure manipulation.

Important aspects for assessment:

Trade-off with the stopgap mitigation: the module blacklist only covers the AEAD path. There are related AF_ALG modules (algif_hash, algif_skcipher, algif_rng, algif_aead) that aren't all affected by the same CVE, but auditing them as part of a clean patch wave is recommended.

Detection and verification

Lead questions

Quick check per host

 

# Check kernel version
uname -r

# algif_aead module status
lsmod | grep algif_aead
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)

# Distribution patch status
# Debian/Ubuntu
apt list --installed 2>/dev/null | grep linux-image
# RHEL/AlmaLinux/Rocky
rpm -qa | grep kernel
# SUSE
zypper search --installed-only -t package kernel-default

 

Falco / eBPF correlation

If you operate Falco or comparable eBPF monitoring, watch for a three-syscall correlation per process: socket(AF_ALG)bind/accept on an aead cipher → setresuid(0,0,0) or setreuid(0,0) within a few seconds. That is the exploit signature pattern that holds across PoC variants.

A concrete Falco rule sketch:

 

- rule: AF_ALG Aead Followed By Setuid
  desc: Unprivileged process opens AF_ALG socket and then transitions to UID 0
  condition: >
    evt.type = socket and
    evt.arg.domain = AF_ALG and
    proc.uid != 0 and
    proc.aname[1] != systemd
  output: >
    Possible Copy Fail exploitation
    (user=%user.name pid=%proc.pid command=%proc.cmdline)
  priority: WARNING

 

The rule alone triggers false positives on legitimate workloads (e.g. some libgcrypt paths). It is meant as a correlation anchor, not a blocking rule — the additional setuid follow-up in the output collection makes the case verifiable.

Audit routine per host

For SMEs without a dedicated SOC team: once a week per host, log uname -r in a central table and compare against the currently recommended patched version. Without automation you get patch drift — and patch drift becomes expensive exactly in high-severity cycles like this one.

Operator recommendation

Operational decision block

If you operate Linux hosts on RHEL/AlmaLinux/Rocky/CentOS Stream — then

apply the distribution patch via dnf upgrade kernel and reboot. If you cannot reboot: KernelCare live patch for EL8/EL9 is available as a stopgap.

If you operate Ubuntu LTS hosts — then

apply the kernel update via apt upgrade linux-image-* plus reboot. KernelCare covers Ubuntu 22.04 LTS (Jammy) including AWS and HWE variants as a live patch.

If you operate Debian stable (bookworm/trixie) — then

patches are available — Debian stable has shipped the updates since early May. If the host has not been updated yet, close that this week. Sid has linux 7.0.4-1.

If you run EC2, Hetzner Cloud, Azure, GCP — then

cloud providers do not patch the hypervisor on your behalf. Your guest kernel has to be updated. On Amazon Linux: AWS security bulletin 2026-027 lists the concrete kernel versions.

If you operate Kubernetes platforms — then

plan a node image update — all worker nodes need the patched kernel; otherwise compromised pods escalate to the host. Container images themselves are not affected (containers share the host kernel).

If you have hosts where AF_ALG applications are NOT used — then

you can deactivate the module as an interim measure: echo "install algif_aead /bin/true" > /etc/modprobe.d/blacklist-algif_aead.conf + reboot. Caution: on the RHEL family the module is built-in, so the initcall must be blacklisted via grubby — or just patch.

 

What we deliberately do not do

What we actually did at Moselwal

Our build containers and production hosts have been running on patched kernels since early May. Concretely:

For customers running their own cloud VMs or container platforms that we do not operate ourselves, we have distributed patch guidance and support if needed with detection scripts or audit routines.

Frequently asked questions about Copy Fail

Do Kubernetes containers or Wolfi images need to be rebuilt because of Copy Fail?+

No. The vulnerability sits in the host kernel, not in the images. Rebuilds would be activity for activity’s sake and only burn pipeline time — that holds for Wolfi just as for any other container base.

Why is the algif_aead kernel module loaded on my Linux system in the first place?+

AF_ALG is a user-space interface to the kernel crypto subsystem. Very few applications use it in production. Disabling it via modprobe blacklist is therefore typically a no-op for normal operations.

How do I verify that the Copy Fail mitigation actually takes effect on my host?+

We reproduce the public PoC from copy.fail after applying the mitigation. A host counts as cleared only when the escalation fails. A configuration line entered is not enough.

Are EC2, Hetzner Cloud, and Azure VMs automatically protected against CVE-2026-31431?+

Not automatically. Managed Kubernetes providers often ship worker images with mitigations included. Self-managed workers on EC2 or bare metal are your responsibility, and part of our audit.

When will the kernel patch for CVE-2026-31431 land in Debian, Ubuntu, and RHEL?+

As of 30 April 2026, no final mainline patch is available. Distributors will ship the patch after backporting. We track the kernel mailing list and apply the fix once it is stable and our validation has run.

As of 4 May 2026, patches have been released for most distributions. Update now! There are now targeted attacks on container environments!

We don't have an in-house security team — who mitigates Copy Fail on production Linux hosts?+

That is exactly what DevSecOps as a Service and our external IT department are for. We mitigate on your behalf, document the procedure in an audit-ready way, and hand back a verified state.

Conclusion

Copy Fail is the first of the two universal Linux LPE vulnerabilities in the May 2026 wave and the one with the strongest external indication: CISA KEV listing, FCEB remediation deadline 15 May 2026, multiple independent threat-intel confirmations of active exploitation. A 732-byte Python vulnerability that affects every Linux kernel since 2017 — that is not the edge case, it's the SME norm.

Operationally the patch is trivial: dnf upgrade kernel or apt upgrade linux-image-* plus reboot. Strategically it is a test of whether your own patch routine is fast enough to hold KEV deadlines without declaring an emergency. Anyone who has not patched between the April 2026 initial disclosure and mid-May has a pipeline weakness, not a complexity problem.

The cluster lesson: Copy Fail and Dirty Frag are variants of the same pattern — in-place optimisations in the kernel that grant unprivileged write primitives into the page cache. If you have one, you have the other ahead of you. The patch pipeline has to treat both CVEs as a connected task, not as two separate tickets.

We audit, mitigate, and validate your hosts against Copy Fail.

You give us access to your Linux hosts — we audit with SBOM inventory, deploy the module blacklist as a stopgap, follow up with the distribution patch in your maintenance window, and reproduce the public PoC before and after each step. You get an audit-ready report back, not a sales follow-up.

This is the operational routine behind DevSecOps as a Service and the External IT Department — platform operations, not advisory-on-paper.

Request audit

Author of this post

[Translate to English:] Foto von Kai Ole Hartwig.

Kai Ole Hartwig

Founder · Moselwal Digitalagentur · OnlyOle

Programming since 2002 – self-taught, set up my own business with KO-Web in 2012, now Moselwal. Over 100 projects, with a focus on security, performance, automation and quality.