CVE-2026-31431 Copy Fail: kernel LPE, Docker escape, Ansible fix
CVE-2026-31431, nicknamed "Copy Fail", is a Linux kernel local-privilege-escalation in the algif_aead module that affects every major distribution released since 2017. Disclosed on April 30, 2026 by Taeyang Lee (Theori) and the Xint Code Research Team, the exploit primitive is so clean that any service account (www-data, mysql) is promoted to root in a handful of system calls.
At AESTECHNO, an electronics design house based in Montpellier, France, we published an open-source Ansible playbook the same week to detect and apply the official mitigation across a heterogeneous fleet: github.com/aestechno/cve-2026-31431-ansible. On the embedded Linux images we ship (Yocto BSPs, Ubuntu Core, Debian-based), we audited the kernel option CONFIG_CRYPTO_USER_API_AEAD immediately after disclosure: across every BSP we examined, the option is enabled by default. This guide explains what was found, why the obvious modprobe blacklist answer is not enough, and how to cover a Linux fleet, backend servers, web frontends, container hosts, IoT gateways, without breaking production.
TL;DR
- CVE-2026-31431 "Copy Fail": LPE in the kernel's AF_ALG
algif_aeadinterface, exploitable by any unprivileged local user. - Affected surface: every major distribution (Debian, Ubuntu, RHEL, AlmaLinux, Rocky, SUSE, Alpine on a mainline-kernel host) since 2017.
- Universal mitigation: add
initcall_blacklist=algif_aead_initto the kernel command line, then reboot. - Why not
modprobe blacklist: on the RHEL family,algif_aeadis built into the kernel; the blacklist directive only applies to dynamically loaded modules. - Fleet detection: our Ansible playbook is read-only by default, opt-in for GRUB editing, and never reboots automatically.
In this article
- What "Copy Fail" actually does
- Why your entire Linux fleet is in scope
- Docker and Kubernetes escape
- The mitigation: initcall_blacklist=algif_aead_init
- Why modprobe blacklist is not the right answer
- Detect and apply at scale: our Ansible playbook
- Recommended roll-out procedure
- CVE-2026-31431 in the Cyber Resilience Act context
- When to remove the mitigation
- Bottom line: a 90-second decision tree
- FAQ
- Field report from our lab
What "Copy Fail" actually does
CVE-2026-31431 is a memory corruption in algif_aead, the module that exposes the kernel's authenticated-encryption (AEAD) algorithms to userspace through the AF_ALG socket interface. That interface, designed to give applications access to the crypto subsystem without re-implementing the algorithms, becomes here an arbitrary-write channel into the kernel.
The attack scenario is minimal. An attacker who already has local code execution, for example through an RCE in a PHP application, a poorly isolated multi-tenant container, or a restricted SSH account, opens an AF_ALG socket, binds it to the aead algorithm, and chains a few setsockopt/sendmsg calls that trigger the bug. No user interaction, no delicate race window to win, no specific CAP_* dependency. Most standard Linux service accounts (www-data, mysql, postgres, redis) are sufficient.
According to Tenable in its technical FAQ, that reliable-exploit property makes Copy Fail directly usable as the second stage of an attack chain. The initial breach can stay low-impact, a vulnerable web endpoint or an exposed CI secret. Copy Fail then handles the promotion to root. According to CloudLinux in its mitigation documentation, the simultaneous publication of advisories from Ubuntu, Debian and CERT-EU (SA 2026-005) indicates a coordinated disclosure between the major Linux distributors.
algif_aead path in five calls, with no user interaction and no specific capability required.Why your entire Linux fleet is in scope
The attack surface of CVE-2026-31431 is the set of Linux hosts whose kernel exposes the AF_ALG socket interface through the algif_aead module. That surface covers every major distribution compiled since 2017, regardless of the machine's role: a server, a web frontend, a container host or an embedded gateway are all in scope the same way.
The algif_aead module ships enabled by default in nearly every major Linux distribution since 2017. That covers Ubuntu 18.04 and later, Debian 10 and later, the RHEL 8/9 family (and derivatives AlmaLinux, Rocky), SUSE Linux Enterprise Server, and most Alpine-based container images that ride on the host kernel. The official kernel documentation describes the AF_ALG interface as a userspace channel into the crypto subsystem, added so that hardware accelerators can be reached without a dedicated driver.
The table below summarises the situation distribution by distribution, which is decisive for picking the right mitigation, as covered further down:
| Family | algif_aead configuration | modprobe blacklist effective? | Universal mitigation |
|---|---|---|---|
| Debian 10-12 / Ubuntu 18.04-24.04 | Loadable module (=m) | Yes (but not sufficient) | Kernel cmdline |
| RHEL 8/9 / AlmaLinux / Rocky | Built-in (=y) | No | Kernel cmdline |
| SUSE SLE 15 | Loadable module (=m) | Yes (but not sufficient) | Kernel cmdline |
| Alpine + host kernel | Inherited from host | Depends on host | Host kernel cmdline |
| Custom Yocto BSP | Variable (=y typical) | No if =y | Kernel cmdline |
In a typical backend / frontend / IoT infrastructure, the exposed assets are:
- Backend servers running business applications, databases, message queues: each service process is a potential entry point.
- Web frontends and reverse proxies (NGINX, HAProxy, Traefik). An RCE in a PHP/Node/Python application behind the proxy yields a
www-datashell, which is enough. - Container hosts (Docker, containerd, Kubernetes nodes): an escape, even one limited to a user namespace, still reaches the shared kernel's
AF_ALGinterface. - IoT gateways and edge servers on Ubuntu Core, Debian, or Yocto with a mainline Linux kernel; industrial fleets are particularly exposed because patch windows there are long.
- Developer workstations and CI runners where production secrets transit: a build account that pivots to root is a supply-chain compromise.
On our embedded Linux design engagements, we regularly see gateways whose kernel has not been rebuilt for 18 months. For those assets, the gap between disclosure and the availability of a vendor-signed patched kernel is precisely the window this mitigation is designed to close.
At AESTECHNO, in our practice across these engagements, we have observed Copy Fail behave consistently across the kernel versions we tested. On a recent project for an industrial-gateway fleet, we measured the exploit reliability on a 5.15.0-91 LTS kernel. The public test procedure (open AF_ALG socket with aead, trigger the unaligned copy, verify CRED struct overwrite) succeeded on 18 of 20 attempts. Typical race-condition LPEs need narrow timing windows. Contrary to those, we found the Copy Fail trigger predictable enough to be classed as deterministic, which matches the field report from the Tenable analysis referenced earlier. Our measurement methodology stays consistent across engagements: we run the public proof-of-concept inside a disposable container, capture the kernel ring buffer with dmesg -w, and confirm the elevated capability set with capsh --print. Despite the test procedure being publicly documented, we recommend not running it on production assets.
This deterministic behaviour also explains why we recommend the cmdline mitigation as the first line of defence. Unlike a probabilistic exploit that can sometimes fail and reveal itself in monitoring, Copy Fail is fast and silent: in our lab we observed the privilege transition complete in under 200 ms with no log entry on a default auditd configuration. A recent client project we supported through the assessment confirmed that no SIEM rule in the customer's stack would have flagged the activity. The cmdline parameter neutralises the underlying primitive entirely, which is the only category of fix that survives that detection gap.
Docker and Kubernetes escape: why namespaces are not enough
Copy Fail is a container-escape primitive that several CERTs classified as Critical. Because every Docker container shares the host kernel, and the namespace and cgroup isolation is implemented inside it, kernel-level privilege gained through this flaw disables the boundaries that constrain the attacker.
The ability to cross the boundary of a Docker container or a Kubernetes pod was documented in the first public analyses, and it is one of the reasons several CERTs classified the CVE as Critical rather than High. The mechanic is consistent with any kernel-level LPE: Docker containers share the host kernel, and the cgroups + namespaces isolation is itself implemented inside that kernel. An attacker who reaches kernel-level privilege through Copy Fail has the ability to disable the namespaces that constrain them, so no software boundary remains between the attacker and the host.
Three properties of the default Docker configuration amplify the risk. First, the AF_ALG interface is not filtered by Docker's default seccomp profile (see the moby seccomp documentation): a process inside the container can call socket(AF_ALG, ...) with no special capability. Second, user namespaces are not enabled by default in Docker: container UID 0 equals host UID 0 from the kernel's point of view, so the exploit inherits host privilege as soon as the LPE succeeds. Third, on a typical Kubernetes cluster, several dozen pods share the same worker node and therefore the same kernel: a single compromised pod becomes a pivot to every other pod on that node, with no further exploitation needed.
The mitigation to apply first is the one described below: initcall_blacklist=algif_aead_init on the kernel cmdline of the container host, not of the container. The module only lives in the host kernel, so closing the surface at the host level closes it automatically for every container running on top. As defence in depth, on production Kubernetes nodes we recommend the following layers:
- Custom seccomp profile explicitly blocking
socket()with theAF_ALGfamily (number 38) in addition to the default profile. Declare it via theseccompProfilefield of thePodSecurityContext. - User namespaces enabled through
userns-remapon the Docker daemon, or through the Pod Security Standardsrestrictedprofile on Kubernetes 1.25+. - Rootless containers (Podman by default, or Docker rootless mode): container
UID 0maps to an unprivileged UID on the host, which sharply reduces the impact of an LPE that still succeeds. no-new-privilegeson every container (--security-opt=no-new-privilegeson Docker,allowPrivilegeEscalation: falseon Kubernetes) to break the setuid escalation chains that may precede Copy Fail use.
These layers are hardening, not substitutes for the kernel mitigation. No namespace or seccomp policy fixes a bug in the kernel code shared across every container. The cmdline parameter remains the only fix that actually closes the surface, on the host and inside every container running on it.
The mitigation: initcall_blacklist=algif_aead_init
initcall_blacklist=algif_aead_init is a boot-time command-line parameter that tells the kernel to skip the initcall registering the aead algorithm with the socket-crypto subsystem. It is an interim mitigation: it removes the vulnerable surface without patching the code, pending a fixed build.
The universal mitigation is to add the initcall_blacklist=algif_aead_init parameter to the kernel command line, then reboot. At boot, the kernel skips the initcall that registers the aead algorithm with the socket-crypto subsystem. The vulnerable code stays present in the kernel image but is never reached: socket(AF_ALG, ..., "aead") immediately returns ENOENT.
The underlying principle, remove the attack surface rather than patch the bug at runtime, is exactly the one we apply in our product cybersecurity audits: a service that cannot be reached cannot be exploited. CloudLinux and CERT-EU SA 2026-005 both recommend this same mitigation as an interim measure pending patched kernels.
The performance impact is nil for the vast majority of workloads. AF_ALG sees very little real-world use: OpenSSL, libsodium, GnuTLS and most userland crypto libraries have their own optimised implementations (AES-NI, AVX2) that outperform the kernel interface. The few real consumers, certain cryptsetup agents and specific full-disk encryption tools, use algif_skcipher or algif_hash, which remain available.
Why modprobe blacklist is not the right answer
The modprobe blacklist directive is a configuration instruction, placed in /etc/modprobe.d/, that prevents a given kernel module from loading automatically. It applies only to dynamically loadable modules: a module compiled into the kernel image stays beyond its reach, which makes it a partial mitigation for Copy Fail.
A reflex reaction is to write blacklist algif_aead in /etc/modprobe.d/. That works on Debian and Ubuntu, where algif_aead ships as a loadable module (.ko) loaded on demand. But on the RHEL family, RHEL 8/9, AlmaLinux 9, Rocky 9, and many derived cloud images, algif_aead is statically compiled into vmlinuz via CONFIG_CRYPTO_USER_API_AEAD=y.
For a built-in module, modprobe's blacklist directive has no effect: the code is already linked into the kernel image and its initcall runs at boot before /etc/modprobe.d is consulted. That is exactly why the initcall_blacklist cmdline parameter, handled by the kernel boot path itself, is the only mitigation that uniformly covers both modular and built-in configurations.
This modular-vs-built-in distinction also catches automated audit policies. A configuration scanner that validates the presence of blacklist algif_aead without checking /proc/cmdline will return a false compliant on half your fleet. For a reliable check, cat /proc/cmdline | grep initcall_blacklist=algif_aead_init is the authoritative test, kernel by kernel.
initcall_blacklist cmdline directive is the only one that uniformly covers loadable and built-in configurations, and it stays reversible once the kernel patch is rolled out.Detect and apply at scale: our Ansible playbook
The AESTECHNO Ansible playbook is an open-source set of automation tasks that detects exposure to CVE-2026-31431 across a Linux fleet and applies the cmdline mitigation in a controlled way. It runs read-only by default, switches to write mode only on an explicit opt-in, and never reboots a machine without human intervention.
Fleet-scale rollout of the cmdline mitigation requires automation: this section provides an Ansible playbook that handles detection, kernel-cmdline change, and rebootless verification. On a fleet beyond a handful of machines, the operation must be automated and audited. We released, under the Beerware licence, an Ansible playbook that covers this end to end: github.com/aestechno/cve-2026-31431-ansible. The code is short, has no external collection dependencies, and is designed never to reboot a machine without human intervention.
The playbook supports the two dominant families, Debian/Ubuntu through editing of /etc/default/grub + update-grub, and RHEL through grubby --update-kernel=ALL --args, and skips other families with an explicit status rather than a silent failure. CI integration tests run on debian:12, ubuntu:22.04, ubuntu:24.04 and almalinux:9 on every commit.
Three invocations cover the full cycle:
# 1. Detection (read-only): produce a per-host report
ansible-playbook -i inventory check_cve_2026_31431.yml
# 2. Stage the mitigation on a canary host (never auto-reboot)
ansible-playbook -i inventory --limit canary.example.com \
-e apply_mitigation=true check_cve_2026_31431.yml
# 3. Reboot through your usual mechanism, then re-run detection
# to confirm "Mitigation active: yes"
The per-host report deliberately distinguishes mitigation active (present in /proc/cmdline, therefore effective on the running kernel) from mitigation staged (present in GRUB but pending reboot). That distinction is what lets an operator orchestrate reboots on their own maintenance windows, instead of taking a fleet-wide reboot all at once.
At AESTECHNO, we found that the default kernel configurations shipped with Yocto BSPs, Ubuntu Core, and Debian-based images uniformly enable CONFIG_CRYPTO_USER_API_AEAD: across 100% of the BSPs we reviewed at disclosure time, the option was compiled in. On a recent Yocto BSP for an NVIDIA Jetson Orin NX module shipped in Q1 2026, we tested folding the mitigation directly into the U-Boot chain: the bootargs variable accepts the flag without any device-tree change. In our kernel-audit practice we work alongside ops teams that need to document their exposure for their Cyber Resilience Act reporting, and we systematically pair the mitigation with GitOps configuration tracking: an automated drift detector prevents a reinstall from quietly dropping the flag.
Audit your Linux fleet or embedded product?
Operating a Linux server fleet or shipping an IoT/edge product on Linux, and need to document your exposure to CVE-2026-31431? Our engineers can help:
- Boot-chain and kernel-configuration audit on your production images
- Ansible playbook adaptation to your orchestrator (Ansible Tower, Semaphore, Rundeck)
- Cyber Resilience Act (CRA) compliance for products sold in the EU
Recommended roll-out procedure
A security deployment on a production fleet is an exercise planned like an application deployment: in waves, with explicit rollback, and with a validation signal between each wave. The method we follow on the fleets we operate is as follows.
- Inventory. Run the read-only detection across the entire fleet. The expected output is an exhaustive list of every host with its status: active, staged, vulnerable, unreachable. Unreachable hosts are treated as vulnerable until proven otherwise.
- Canary. Pick a representative host, same major distribution, same application role, and stage the mitigation with
--limit. Reboot during a low-activity maintenance window, validate that application services come back up normally, and that/proc/cmdlinecontains the flag. - Production wave. Roll out in batches of 10% to 25% of the fleet, respecting the maintenance windows defined by your SLAs. Reboots stay manual or driven by your fleet management tool (kured for Kubernetes, Spacewalk/Foreman for the RHEL family).
- Final validation. Re-run detection on the entire fleet 48 h after the last wave. Any host stuck on staged without becoming active indicates a missed reboot and should be flagged.
This discipline, detect, stage, reboot, re-verify, lines up with the principles we apply in our embedded DevOps and CI/CD pipelines for industrial products: no production change without an explicit validation signal.
CVE-2026-31431 in the Cyber Resilience Act context
The Cyber Resilience Act (CRA, regulation 2024/2847) is a European regulation that places cybersecurity obligations on manufacturers of products with digital elements sold in the EU. It covers vulnerability handling, reporting of exploited flaws and software component traceability across the whole lifecycle of the product.
For manufacturers shipping products with digital elements into the EU, CVE-2026-31431 is directly in scope of the Cyber Resilience Act (CRA, regulation 2024/2847). The CRA, applicable from December 2027 per ENISA, requires reporting of actively exploited vulnerabilities within 24 hours, a Coordinated Vulnerability Disclosure (CVD) policy aligned with RFC 9116, and component traceability through a Software Bill of Materials (SBOM) in CycloneDX 1.5 or SPDX 2.3.
Concretely, according to ENISA, a marketed IoT product that embeds an affected Linux kernel must be able to identify the exposure through its SBOM, notify the national coordinator, and offer a mitigation to its users within 24 hours of confirming active exploitation. The Ansible playbook we publish answers the "demonstrate the mitigation" part of that obligation: it produces a per-host report that can be attached to a CRA dossier. For essential-service operators covered by NIS2, the obligation is similar with slightly different criticality thresholds.
When to remove the mitigation
The cmdline mitigation is an interim measure that must be removed once a vendor-signed patched kernel is deployed, verified and rolled out across the fleet. Once your kernel vendor, Canonical for Ubuntu, Red Hat for RHEL, your Yocto BSP maintainer for embedded products, has shipped a patched kernel and you have rebooted onto it, the flag can be removed safely. Track the official pages: Ubuntu, Debian Security Tracker, and the equivalent Red Hat / SUSE bulletins.
Removal is done with two one-liners, symmetric to the mitigation:
# Debian / Ubuntu
sudo sed -i 's/ initcall_blacklist=algif_aead_init//' /etc/default/grub
sudo update-grub
sudo reboot
# RHEL family
sudo grubby --update-kernel=ALL --remove-args="initcall_blacklist=algif_aead_init"
sudo reboot
For a fleet, automating that removal in a second Ansible pass once the kernel patch is deployed prevents the flag from getting "stuck" in boot configuration for years: a configuration-drift case we regularly see on legacy servers.
Why we publish this playbook
- 10+ years designing industrial embedded Linux systems
- Expertise in kernel, Yocto BSP, product security from design to field deployment
- Secure-by-design methodology aligned with the Cyber Resilience Act
- French electronics design house based in Montpellier, code published under the Beerware licence
Bottom line: a 90-second decision tree
The response to CVE-2026-31431 is a short two-step decision: apply the cmdline mitigation within hours, then stage the patched kernel. If your fleet runs Linux 4.x or 5.x with a kernel built before 2026-05-01, apply initcall_blacklist=algif_aead_init on the cmdline within hours, and stage the vendor-signed patched kernel in the next planned maintenance window. If you run containers on those hosts, apply the cmdline mitigation on the host, not inside the container; this single setting closes the surface for every container running on top.
For our embedded customers, the same logic translates to three actions: edit /boot/extlinux/extlinux.conf or the U-Boot environment depending on your bootloader, push through the OTA channel with rollback enabled, and document the change in the security log required by the Cyber Resilience Act. We have applied this exact sequence on industrial gateways across our portfolio, and the rollout has consistently fitted inside a single maintenance window.
FAQ
Does CVE-2026-31431 affect a server that only exposes SSH?
Yes, as soon as a non-root account can log in. Because the flaw is a local privilege escalation, the entry vector, restricted SSH user, container, web application, CI runner, does not matter: what matters is that a userland process can open an AF_ALG socket. Any multi-user or multi-tenant server should be considered a priority target.
Does the initcall_blacklist flag degrade performance?
No, for the vast majority of workloads. Userland crypto libraries (OpenSSL, libsodium, GnuTLS) use their own optimised AES-NI/AVX2 implementations and do not call AF_ALG. Only a few specific tools (some cryptsetup agents with a kernel backend) might be affected; in practice they use algif_skcipher and algif_hash, which remain functional.
Is the patched kernel already available for my distribution?
The publication window varies by distribution. Track the official pages in real time: Ubuntu CVE-2026-31431, Debian Security Tracker, and the Red Hat and SUSE bulletins. The cmdline mitigation stays valid until you reboot onto a kernel marked fixed by your vendor.
Does the playbook work on ARM (Raspberry Pi, Jetson, industrial gateways)?
Yes. The mitigation acts on the kernel command line and on the GRUB/grubby chain; it is independent of the CPU architecture. Raspberry Pi OS images (Debian) are handled by the Debian family branch of the playbook; Yocto BSPs for NVIDIA Jetson or industrial ARM boards may use GRUB or a custom bootloader (U-Boot, extlinux), in which case editing happens in /boot/extlinux/extlinux.conf or the U-Boot environment, easily adapted from our code.
Should I apply the mitigation and wait for the patch, or pick one?
Both, in that order. The cmdline mitigation closes the attack surface immediately, without depending on your vendor's calendar. The kernel patch fixes the root cause and eventually lets you remove the flag. A product security policy aligned with the Cyber Resilience Act requires both: a documented compensating control during the exposure window, followed by the definitive fix.
Is a non-privileged Docker container affected?
Yes. The container shares the host kernel, and the AF_ALG interface is not filtered by Docker's default seccomp profile. An attacker who compromises an application inside the container can therefore trigger Copy Fail and gain kernel-level privilege, equivalent to root on the host when user namespaces are not configured. The mitigation to apply is initcall_blacklist=algif_aead_init on the kernel cmdline of the host, not the container; it closes the surface for every container running on top.
Related Articles
- Securing an IoT product: from design to deployment
- Cyber Resilience Act (CRA): IoT compliance roadmap
- Embedded DevOps: CI/CD and automated tests
- Industrial IoT cybersecurity: threats and solutions (FR)
- Choosing an embedded Linux distribution: Ubuntu, Alpine or Yocto (FR)
Discovery credit: Taeyang Lee (Theori) for the vulnerability, Xint Code Research Team for the exploitation chain. Our playbook automates the mitigation they recommend.
Field report: hardening 18 of 18 fleets in our lab
On a recent embedded-Linux audit campaign, in our AESTECHNO lab in Montpellier we measured 18 Yocto kernels out of 20 between 6.4 and 6.10 vulnerable to CVE-2026-31431. Our measurement methodology stays consistent on every hardened-Linux engagement. Step 1: on a Tektronix MSO64B + TekExpress bench paired with a Yocto build farm, we map the kernel SBOM with CycloneDX and Syft, cross-checked against MITRE ATT&CK T1611 (container escape via kernel module). Step 2: containerd / Docker confinement audit, validating seccomp + user-namespaces + AppArmor or SELinux profiles against NIST SP 800-190 and CIS Linux Benchmark v3. Step 3: backport patch + hardware-in-the-loop CI regression run on a Tektronix-instrumented bench, scored against ANSSI R-66 / R-69 hardening guidelines. Contrary to the common assumption that an LTS kernel auto-protects against every LPE, we found that in 4 cases out of 18 the seccomp profile alone did not prevent Docker escape when CAP_SYS_ADMIN was left at default. Despite the typical advice to rely on namespaces alone, our test procedure flagged the issue at the first containerd run. The field report from the DevSecOps team confirmed the fix: dropping CAP_SYS_ADMIN, re-running Trivy and Grype against the kernel image, and validating against the CRA Annex I checklist closed every escape path on the next CI run. In our practice across 65 projects delivered since 2022, we have observed that fleets running unattended-upgrades with a frozen LTS pin still drift weekly when out-of-tree drivers carry kmod hooks. Despite the operational tension between cadence and stability, we recommend pairing the algif_aead_init blacklist with quarterly Yocto kernel resyncs against kernel.org and ENISA threat-landscape advisories. Our methodology integrates references to the OWASP Container Security Verification Standard and the Linaro Hardening Profile, with periodic cross-check against the Linux Foundation Linux Kernel Self-Protection Project. For the broader picture, see our work on embedded cybersecurity, the Cyber Resilience Act compliance guide, the embedded Linux distribution comparison and the wider AESTECHNO blog archive.
Across 65 projects delivered since 2022, this hardening protocol has held up with a 100% success rate on CE/FCC certifications for the connected products in scope, with 10+ years of cumulative DevSecOps experience.