Detect and mitigate CVE-2026-31431 (Copy Fail) on Linux systems.
Project description
copyfail-guard
A zero-dependency Python CLI that detects and mitigates CVE-2026-31431 ("Copy Fail") on Linux. Works on Debian/Ubuntu, RHEL/Rocky/AlmaLinux, Fedora, and SUSE.
Background
CVE-2026-31431 is a logic bug in the algif_aead (AF_ALG AEAD socket) kernel
interface that lets an unprivileged local user perform a controlled 4-byte write
into the page cache of any readable file, leading to root privilege escalation.
CVSS 7.8, present since kernel 4.14, patched in stable releases starting April 2026.
A public PoC exists and the vulnerability is listed in CISA KEV.
What this tool does
| Subcommand | Action |
|---|---|
detect |
Combines four signals (kernel version, /proc/modules, modules.builtin, modprobe config) into one of six verdicts |
fix |
Atomically writes an install algif_aead /bin/false blacklist and runs modprobe -r algif_aead |
fix is intentionally minimal — it does not call your package manager.
Permanent remediation requires upgrading the kernel through your distribution's
normal update mechanism.
Install
pip install copyfail-guard
Or run directly from a checkout without installing:
PYTHONPATH=src python3 -m copyfail_guard detect
Usage
copyfail-guard [--json] [--dry-run] [--quiet] [detect | fix]
detect (default)
$ copyfail-guard
[copyfail-guard] CVE-2026-31431 (Copy Fail) — VULNERABLE
Distribution: Ubuntu 24.04.1 LTS (debian family)
Kernel: 6.8.0-50-generic (branch 6.12, fixed at 6.12.85)
Module: algif_aead — loaded as .ko
Mitigation: none
Recommended actions:
1. Apply mitigation now:
sudo copyfail-guard fix
2. Update the kernel for a permanent fix:
Update the kernel on this system to 6.12.85 or later, then reboot.
fix
Always preview with --dry-run before applying:
$ sudo copyfail-guard --dry-run fix
[copyfail-guard] fix — DRY RUN (no changes made)
[dry] Would write modprobe blacklist [/etc/modprobe.d/cve-2026-31431-copyfail-guard.conf]
[dry] Would attempt to unload algif_aead (not currently loaded)
[dry] Would append audit record [/var/log/copyfail-guard.log]
$ sudo copyfail-guard fix
[copyfail-guard] fix — OK
[ ok ] Pre-flight checks (Linux, host, root)
[ ok ] Wrote modprobe blacklist [/etc/modprobe.d/cve-2026-31431-copyfail-guard.conf]
[ ok ] Unloaded algif_aead [algif_aead]
[ ok ] Appended audit record [/var/log/copyfail-guard.log]
Next step for a permanent fix:
Update the kernel to a CVE-2026-31431-patched version using your
distribution's normal update mechanism, then reboot.
JSON output
--json emits a structured document on stdout, suitable for jq, Ansible, or SOAR pipelines:
$ copyfail-guard --json | jq .verdict
"vulnerable"
$ copyfail-guard --json | jq '{verdict, kernel: .kernel.patched_threshold}'
{
"verdict": "vulnerable",
"kernel": "6.12.85"
}
Exit codes
| Code | Meaning |
|---|---|
0 |
Safe — verdict is patched, mitigated, or not_applicable; or fix succeeded |
1 |
Vulnerable — verdict is vulnerable or unmitigable_builtin |
2 |
Error — state could not be determined, precondition refused, or fix failed |
Verdicts
| Verdict | Description |
|---|---|
patched |
Running kernel is at or beyond the fixed version |
mitigated |
Kernel is vulnerable but algif_aead is blocked by modprobe config |
not_applicable |
Kernel is vulnerable but algif_aead is not present on this system |
vulnerable |
Kernel is vulnerable, module is loadable, no mitigation in place |
unmitigable_builtin |
algif_aead is compiled into the kernel image — modprobe mitigation has no effect; kernel upgrade required |
unknown |
Kernel version could not be parsed or is outside the assessed range |
Removing the mitigation
After upgrading to a patched kernel:
sudo rm /etc/modprobe.d/cve-2026-31431-copyfail-guard.conf
sudo reboot
Notes
Containers. fix refuses to run inside a container because /proc/modules
reflects the host kernel but the container has no authority to load or unload
modules. Run copyfail-guard on the host directly.
Built-in algif_aead. Some kernels compile algif_aead directly into the
image (CONFIG_CRYPTO_USER_API_AEAD=y). modprobe mitigation has no effect in
this configuration; the only remediation is a kernel upgrade. The tool reports
unmitigable_builtin and skips the fix step.
blacklist vs install … /bin/false. Both directives block auto-loading,
but install algif_aead /bin/false cannot be overridden by an explicit
modprobe algif_aead invocation. copyfail-guard always installs the stronger
form. If your system already has a plain blacklist directive, the tool reports
mitigated but emits a note recommending the upgrade.
SELinux/AppArmor. Writes to /etc/modprobe.d/ on RHEL inherit
system_u:object_r:modules_conf_t:s0 from the parent directory — no manual
relabel is needed.
initramfs. algif_aead is not included in the boot image on any major
distribution, so running update-initramfs -u or dracut -f is not required
after installing the blacklist.
Development
git clone https://github.com/ctzisme/copyfail-guard
cd copyfail-guard
PYTHONPATH=src python3 -m unittest discover tests # stdlib only, no pytest needed
The test suite uses fixture filesystems under tests/fixtures/ and runs fully
on macOS without a real Linux environment. Each fixture provides a synthetic
/etc/os-release, /proc/modules, and
/lib/modules/<rel>/{modules.dep,modules.builtin} tree.
License
Apache 2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file copyfail_guard-0.0.3.tar.gz.
File metadata
- Download URL: copyfail_guard-0.0.3.tar.gz
- Upload date:
- Size: 35.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3b3261b875113c03f4ab11af75c50f97777da7d972c636d69a69baa7b6c5b7c
|
|
| MD5 |
c9beacadd57bff32acca7de73698f820
|
|
| BLAKE2b-256 |
4c9032b26e02b48882586f5cf515779a2a39c0f6c49e8cc1a0e174614e43fc5c
|
Provenance
The following attestation bundles were made for copyfail_guard-0.0.3.tar.gz:
Publisher:
python-publish.yml on ctzisme/copyfail-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
copyfail_guard-0.0.3.tar.gz -
Subject digest:
a3b3261b875113c03f4ab11af75c50f97777da7d972c636d69a69baa7b6c5b7c - Sigstore transparency entry: 1436167911
- Sigstore integration time:
-
Permalink:
ctzisme/copyfail-guard@b3df73c93053101bc0357a1812bbcb868f62580c -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/ctzisme
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@b3df73c93053101bc0357a1812bbcb868f62580c -
Trigger Event:
release
-
Statement type:
File details
Details for the file copyfail_guard-0.0.3-py3-none-any.whl.
File metadata
- Download URL: copyfail_guard-0.0.3-py3-none-any.whl
- Upload date:
- Size: 28.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
021e8bcc736e8616bb01530e37563761e75b6b60fa93e5a0bc381562fda71076
|
|
| MD5 |
24a1b0b6bba3562788c458c940000f44
|
|
| BLAKE2b-256 |
ea584fd023506b64d0cd9093d23ed86173ff436a39c15dcb345ff6dbd55cc4f0
|
Provenance
The following attestation bundles were made for copyfail_guard-0.0.3-py3-none-any.whl:
Publisher:
python-publish.yml on ctzisme/copyfail-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
copyfail_guard-0.0.3-py3-none-any.whl -
Subject digest:
021e8bcc736e8616bb01530e37563761e75b6b60fa93e5a0bc381562fda71076 - Sigstore transparency entry: 1436167925
- Sigstore integration time:
-
Permalink:
ctzisme/copyfail-guard@b3df73c93053101bc0357a1812bbcb868f62580c -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/ctzisme
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@b3df73c93053101bc0357a1812bbcb868f62580c -
Trigger Event:
release
-
Statement type: