
Read-only Bash checker for the Copy Fail Linux kernel vulnerability (CVE-2026-31431)
A small, dependency-light Bash script that tells you whether your Linux system is exposed to the Copy Fail local privilege-escalation vulnerability (CVE-2026-31431).
The script is read-only: it never exploits the bug, never loads kernel modules, and never modifies the system.
Copy Fail is a logic bug in the Linux kernel's authencesn AEAD cryptographic template, reachable from userspace through the AF_ALG (algif_aead) socket interface.
| Field | Value |
|---|---|
| CVE | CVE-2026-31431 |
| Disclosed | 2026-04-29 |
| CVSS v3.1 | 7.8 (High) |
| Class | Local Privilege Escalation |
| Affected component | crypto/authencesn + crypto/algif_aead |
| Introduced in | 2017 (in-place AEAD optimization in algif_aead.c) |
| Mainline fix | commit a664bf3d603d, merged 2026-04-01 |
An unprivileged local user can trigger a deterministic, controlled 4-byte write into the page cache of any file they can read. A public proof-of-concept (732 bytes of Python) uses this primitive to overwrite a setuid binary and obtain root on essentially every mainstream distribution shipped since 2017.
Every Linux distribution that ships a kernel built since 2017 with algif_aead enabled. Confirmed-affected families include:
# Download the script
curl -fsSLO https://raw.githubusercontent.com/samanzamani/copy-fail-checker/main/check-copy-fail.sh
# Make it executable
chmod +x check-copy-fail.sh
# Run it
./check-copy-fail.sh
Or clone the repo:
git clone https://github.com/samanzamani/copy-fail-checker.git
cd copy-fail-checker
./check-copy-fail.sh
The script does not require root. Running it as your normal user gives the most realistic view of the attack surface, because that is exactly the context an attacker would have.
The script runs three independent checks and combines them into a single verdict.
It reads /etc/os-release and uname -r, then compares your running kernel against the official fixed version published by your distribution's security team. The version table currently covers:
If your distribution is not in the table, the script falls back to the runtime checks below.
algif_aead module statusThe script inspects four things without modifying anything:
lsmod)modinfo)/etc/modprobe.d, /usr/lib/modprobe.d, or /run/modprobe.d/boot/config-<uname> or /proc/config.gzA blacklisted, unloaded and not built-in module closes the attack surface even on an unpatched kernel.
AF_ALG socket reachabilityThe most reliable signal is what an attacker would actually see. The script uses a tiny Python probe (socket.socket(AF_ALG, SOCK_SEQPACKET, 0) followed by bind() to the authencesn(hmac(sha256),cbc(aes)) AEAD template) to find out whether AF_ALG sockets can be created and bound from an unprivileged context. The probe creates, binds, and immediately closes the socket without leaving anything exploitable.
If python3 is not installed the probe is skipped and the verdict relies on checks 1 and 2.
For pipelines, configuration management, or fleet scanning, pass --json:
./check-copy-fail.sh --json
Example output:
{
"verdict": "vulnerable",
"distro_id": "ubuntu",
"distro_version_id": "24.04",
"kernel": "6.8.0-31-generic",
"patched_version": "",
"kernel_status": "unknown",
"module_loaded": 0,
"module_builtin": 0,
"module_available": 1,
"module_blacklisted": 0,
"af_alg_status": "reachable"
}
This is the only complete fix. After updating, reboot so the new kernel is actually running.
# Debian / Ubuntu
sudo apt update && sudo apt full-upgrade && sudo reboot
# RHEL / AlmaLinux / Rocky / CentOS Stream
sudo dnf clean metadata && sudo dnf upgrade && sudo reboot
# openSUSE / SLES
sudo zypper refresh && sudo zypper update && sudo reboot
# Amazon Linux 2023
sudo dnf upgrade --releasever=latest && sudo reboot
algif_aeadIf you cannot reboot into a patched kernel right now, blacklist the vulnerable module. This breaks any application that legitimately uses AF_ALG AEAD ciphers (rare on most servers — verify in a staging environment first).
# Persist the blacklist across reboots
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
# Unload it from the running kernel right now
sudo rmmod algif_aead 2>/dev/null || true
If the module is built-in, blacklisting will not work but it is possible to disable the initcall. A reboot is necessary.
sudo grubby --update-kernel=ALL --args="initcall_blacklist=algif_aead_init"
sudo reboot
For containerized workloads, also block the AF_ALG socket family from your seccomp profile so a compromised container cannot reach the kernel surface.
== System information ==
[INFO] Distribution : Ubuntu 24.04.2 LTS (ubuntu 24.04)
[INFO] Kernel : 6.8.0-31-generic
== Check 1 / 3 — Kernel version ==
[WARN] No vendor-fixed kernel version is recorded for ubuntu 24.04.
[WARN] Falling back to runtime mitigation checks below.
== Check 2 / 3 — algif_aead kernel module ==
[WARN] algif_aead is not loaded but can be autoloaded on demand (no blacklist found).
== Check 3 / 3 — AF_ALG socket reachability ==
[VULN] AF_ALG sockets are reachable from this unprivileged context.
== Verdict ==
[VULN] This system appears to be VULNERABLE to CVE-2026-31431.
[VULN] Apply the vendor kernel update or blacklist algif_aead as a temporary mitigation.
uname -r. If you are running an out-of-tree or rebuilt kernel, the version comparison may not reflect whether the fix was actually backported.blocked_permission for AF_ALG simply because seccomp is in effect — the host kernel itself may still be vulnerable.MIT — use, modify, and ship freely. No warranty.
| Distribution | Patched kernel (≥) |
|---|
| AlmaLinux / RHEL / Rocky / CentOS 8 | 4.18.0-553.121.1.el8_10 |
| AlmaLinux / RHEL / Rocky / CentOS 9 | 5.14.0-611.49.2.el9_7 |
| AlmaLinux / RHEL / Rocky / CentOS 10 | 6.12.0-124.52.2.el10_1 |
| Ubuntu 26.04+ ("Resolute") | not affected |
| Ubuntu 18.04 – 25.10 | rolling, see apt |
| Debian (all suites) | rolling, see DSA |
| Verdict | Exit code | Meaning |
|---|
patched | 0 | Running kernel is at or above the vendor-fixed version. |
mitigated | 0 | AF_ALG is blocked and the module is not loaded. |
likely_mitigated | 0 | Module is blacklisted and not loaded; no live probe was possible. |
vulnerable | 1 | Kernel is unpatched and algif_aead / AF_ALG is reachable. |
unknown | 2 | Not enough signal to decide. Treat as potentially vulnerable. |
not_applicable | 3 | Not running on Linux. |