Skip to content

About

Detection Only.. working on an exploit PoC

Topics

Resources

Stars

26 stars

Watchers

0 watching

Forks

Latest commit

 

History

27 Commits

Folders and files

Repository files navigation

CVE-2026-31431 — Copy Fail — Vulnerability Detection Script

Detection only. A working PoC already exists at copy.fail/#exploit. This script is for sysadmins and security teams determining where they are vulnerable — or still vulnerable after patching.


What's this about?

On April 29th 2026, a vulnerability called Copy Fail (CVE-2026-31431) was publicly disclosed by the Xint Code Research Team. It's a logic bug that has been quietly present in the Linux kernel since roughly 2017 — nearly a decade — and lets any unprivileged local user get root.

Not "get root under specific conditions with some luck and a good tailwind." Just... get root. Reliably. On essentially every major Linux distribution.

It affects Ubuntu, Amazon Linux, RHEL, SUSE, and anything else running a mainstream kernel from the last ~8 years. Same script, no recompilation, no per-distro tweaks required.

Yes, it's as bad as it sounds.

The short version of how it works

The Linux kernel has a crypto subsystem accessible to unprivileged users via AF_ALG sockets. There is a mechanism called splice() that can feed file data directly into that subsystem without copying it — which means the kernel's in-memory cached copy of a file (the "page cache") ends up inside a cryptographic operation.

One specific algorithm — authencesn, used for IPsec Extended Sequence Numbers — has a quirk where it uses the output buffer as scratch space and writes 4 bytes slightly past where it is supposed to. Normally harmless. But when page cache pages from a setuid binary like /usr/bin/su end up chained into that output buffer (thanks to a 2017 "optimisation" in algif_aead.c), those 4 bytes land directly in the kernel's cached copy of the binary.

The operation fails with an error. The kernel never marks that page as dirty. The on-disk file is untouched. File integrity tools checking on-disk checksums see nothing wrong.

But the page cache is what gets executed. And su is setuid root.

The full technical writeup is at xint.io and is genuinely worth reading.


What the scripts check

Python script — 13 checks

Seven from the original release plus six new checks added to close detection gaps:

# Check What it looks for
1 Kernel version Is this kernel in the affected range (4.10–6.14)?
2 Patch presence Is the fix commit actually in your running kernel?
3 algif_aead module Is the vulnerable module loaded or loadable?
4 CONFIG_CRYPTO_AUTHENC (new) Is CONFIG_CRYPTO_AUTHENC built-in (=y) or a module (=m)? This single option builds both authenc and authencesn. Built-in means the modprobe blacklist mitigation does nothing.
5 CONFIG_CRYPTO_USER_API_AEAD (new) Is the AF_ALG AEAD userspace interface even compiled in? If not, the entire exploit path is closed at compile time.
6 AF_ALG socket Can an unprivileged user open one right now?
7 Python os.splice Is the pure-Python exploit path available?
8 Setuid binaries Extended list of readable setuid-root targets present on the system.
9 Mitigations AppArmor, SELinux, seccomp — what's in place?
10 User namespaces (new) Are unprivileged user namespaces enabled? (Does not block Copy Fail directly, but affects the broader local privesc surface.)
11 Transparent hugepages (new) THP status — can affect page cache alignment and exploit reliability.
12 Environment detection (new) Docker/container/VM context — containers share the host kernel; the host is what needs patching.
13 Root-user warning (new) Warns if running as root, since several checks give false positives for root regardless of unprivileged restrictions.

Shell script — 10 checks

The Bash script covers the same core detection logic but omits three Python-specific items:

# Check Notes
1 Kernel version
2 Patch presence
3 algif_aead module
4 AF_ALG socket Uses Python as a helper if available; falls back to kernel config inference
5 Setuid binaries Extended list, same as Python version
6 Mitigations AppArmor, SELinux, seccomp
7 CONFIG_CRYPTO_AUTHENC
8 User namespaces
9 Transparent hugepages
10 Environment detection

Not present in shell script (vs Python):

Missing check Reason
CONFIG_CRYPTO_USER_API_AEAD Not yet implemented — planned
Python os.splice availability Not applicable to a shell script
Root-user warning Not yet implemented — planned

Neither script will fix anything or exploit anything. They tell you the truth about your system so you can act on it.


Requirements

  • Python 3.6+
  • No external dependencies — stdlib only
  • No root required (intentionally — we check what an unprivileged attacker can see)
  • Recommended: run as a non-root user — some checks (AF_ALG socket, setuid stat) always succeed for root and will report false positives

Usage

# Clone or download the script, then:
python3 cve-2026-31431-detect.py

That's it. Colour-coded report with a summary at the end.

Exit codes

The script exits with a non-zero code on vulnerable findings, making it suitable for pipeline use:

Code Meaning
0 No vulnerable conditions found
1 One or more vulnerable conditions found
# Example: fail a CI step if the host is vulnerable
python3 cve-2026-31431-detect.py
rc=$?
if [ $rc -eq 1 ]; then
  echo "VULNERABLE — block deployment"
elif [ $rc -ne 0 ]; then
  echo "ERROR — script failed to complete (exit $rc)"
fi

Example output

CVE-2026-31431 'Copy Fail' — Vulnerability Detection
authencesn page cache corruption / local privilege escalation
Running as uid=1001, euid=1001

=== Kernel Version ===
  [VULNERABLE] Kernel version
          Reason : Kernel is in the vulnerable range (4.10 – 6.14)
          Detail : Release: 6.12.0-124.45.1.el10_1 — patch status must be confirmed

=== CONFIG_CRYPTO_AUTHENC (Kernel Config) ===
  [VULNERABLE] CONFIG_CRYPTO_AUTHENC
          Reason : Built as module (=m): auto-loads on AF_ALG bind(); modprobe blacklist is the correct mitigation

=== CONFIG_CRYPTO_USER_API_AEAD (Kernel Config) ===
  [VULNERABLE] CONFIG_CRYPTO_USER_API_AEAD
          Reason : AF_ALG AEAD interface is a loadable module — unprivileged users can access the crypto subsystem via AF_ALG sockets

...

  SYSTEM IS LIKELY VULNERABLE TO CVE-2026-31431

  Recommended actions:
    1. Apply your distribution's kernel update for CVE-2026-31431
    2. Until patched, blacklist the module:
         echo 'install algif_aead /bin/false' > /etc/modprobe.d/disable-algif-aead.conf
         rmmod algif_aead 2>/dev/null
       NOTE: this is ONLY effective when CONFIG_CRYPTO_AUTHENC=m (module).
       If CONFIG_CRYPTO_AUTHENC=y (built-in), patching is the only fix.

Shell version (for DevSecOps pipelines)

A companion Bash script (cve-2026-31431-detect.sh) is available for environments where Python is not present or where shell-native tooling is preferred. It performs 10 of the 13 checks — see the check comparison table above for details of what differs.

# Basic run
bash cve-2026-31431-detect.sh

# JSON output — suitable for SIEM ingestion, Ansible facts, log aggregation
bash cve-2026-31431-detect.sh --json > scan-results.json

# Quiet mode — only print the summary (useful in CI logs)
bash cve-2026-31431-detect.sh --quiet

# Disable ANSI colour (for log files)
bash cve-2026-31431-detect.sh --no-colour

The shell script uses the same exit codes (0 = OK, 1 = vulnerable) and produces equivalent JSON output for pipeline consumption. Where Python 3 is available on the system, the shell script uses it to perform the live AF_ALG socket test; otherwise it falls back to kernel config inference.


Fixing it

The real fix is patching your kernel. Check your distribution's security advisories.

Distribution Where to look
Ubuntu ubuntu.com/security/CVE-2026-31431
RHEL / Amazon Linux dnf update kernel
SUSE zypper update kernel-default
Debian apt update && apt upgrade

Temporary mitigation (module builds only)

If the CONFIG_CRYPTO_AUTHENC check reports =m (built as a module, not built-in), you can blacklist it:

echo 'install algif_aead /bin/false' > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null

Important: this mitigation has no effect if CONFIG_CRYPTO_AUTHENC=y (built-in). In that case, patching the kernel is the only fix. The CONFIG_CRYPTO_AUTHENC check in the script tells you which situation you're in. Note that CONFIG_CRYPTO_AUTHENC is the correct kernel config key — it builds both the authenc and authencesn modules from a single option.

This may affect IPsec if you are using it — verify before deploying fleet-wide.

The upstream fix

The upstream fix is this commit — it reverts the 2017 in-place AEAD optimisation in algif_aead.c, separating the source and destination scatterlists so page cache pages can no longer end up in the writable destination.


Containers and VMs

If you are running this inside a Docker container, Kubernetes pod, or other container environment, the script will warn you: containers share the host kernel. The vulnerability lives in the kernel, not the container image. You must assess and patch the host.


DevSecOps integration examples

# GitHub Actions
# The step will naturally fail and block the pipeline when the script exits 1.
# No extra configuration needed — non-zero exit codes fail steps by default.
- name: Check CVE-2026-31431
  run: |
    python3 cve-2026-31431-detect.py
    rc=$?
    if [ $rc -eq 1 ]; then
      echo "VULNERABLE — pipeline blocked"
      exit 1
    elif [ $rc -ne 0 ]; then
      echo "ERROR — detection script failed to complete (exit $rc)"
      exit $rc
    fi
# Ansible
# Uses playbook_dir to ensure the script path resolves correctly.
# failed_when checks for any non-zero exit (vulnerability OR script error).
- name: Check for CVE-2026-31431
  script: "{{ playbook_dir }}/cve-2026-31431-detect.py"
  register: cve_check
  failed_when: cve_check.rc != 0
# Nagios / monitoring check (shell script — supports exit codes natively)
bash cve-2026-31431-detect.sh --quiet
# exit 0 = OK, exit 1 = CRITICAL (vulnerable)
# JSON output for SIEM / log aggregation (shell script)
bash cve-2026-31431-detect.sh --json --quiet > /var/log/cve-2026-31431-$(hostname)-$(date +%Y%m%d).json

Disclosure timeline

Date Event
2026-03-23 Reported to Linux kernel security team
2026-03-24 Acknowledged
2026-03-25 Patches proposed and reviewed
2026-04-01 Fix committed to mainline kernel
2026-04-22 CVE-2026-31431 assigned
2026-04-29 Public disclosure

Credit to Taeyang Lee at Theori for the original research insight, and the Xint Code Research Team for the full disclosure writeup.


Contributing

Found a false positive? A distribution this misses? A kernel config that should be checked? PRs welcome. The goal is accurate signal, not just scary red text.

Disclaimer

This tool is provided as-is for defensive security purposes. Point it at systems you are authorised to assess. Don't be weird about it.

About

Detection Only.. working on an exploit PoC

Topics

Resources

Stars

26 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages