
Passive Linux host scanner that classifies exposure to CVE-2026-31431 via kernel version, distro changelog, module status, and AF_ALG reachability, with JSON output for SIEM integration.
Authors/Contributors: Patrick Doyle (Author/Maintainer), Effie Renard (Co-Author), Kimberly-Lee Banks (Co-Author), Chris F. (Support/Code Review)
AI Disclosure: Claude Code used for writing tests files, writing test data, and a code security review. All edits were manually audited by one of the contributors.
Single statically-linked Go binary that classifies a Linux host's exposure to CVE-2026-31431.
The tool is passive. It does not exploit the bug. The mechanism probe (see safety statement below) issues exactly two syscalls and never touches the vulnerable code path.
| Signal | Source | Flag |
|---|
| Kernel version vs. upstream fix | uname(2) | --kernel-version |
| Distro changelog mentions the CVE | apt/rpm/apk or on-disk changelog.Debian.gz | --changelog |
algif_aead module status | /proc/modules, modprobe.d, /lib/modules | --module |
| Vulnerable surface reachable | socket(AF_ALG) + bind(authencesn(...)) | --mechanism |
| Compiled into vmlinux | /boot/config-$(uname -r) or A (one-/proc/config.gz | (part of --module) |
If no check flags are given, all four run.
| Mode | Trigger | Use case |
|---|---|---|
| Pretty styled (Default) | TTY stdout, no --format override, no NO_COLOR env | Interactive shell runs |
| Plain text | non-TTY stdout, OR --format=text, OR NO_COLOR=1, OR --no-color | Shell Scripts, Pipes |
| JSON | --format=json | Syslog/SIEM ingest, Shell Scripts |
| Quiet | --quiet | Exit code only (automation/scripts) |
Force pretty when piped: cvecheck --pretty | tee report.txt.
Force plain in a TTY: cvecheck --no-color or NO_COLOR=1 cvecheck.
The probe issues exactly two syscalls socket(AF_ALG, SOCK_SEQPACKET, 0), and bind(fd, &SockaddrALG{Type:"aead", Name:"authencesn(hmac(sha256), cbc(aes))"}). It's then followed by close(fd). It performs no setsockopt for a key, no accept, no sendmsg, no splice, and no pipe creation. The vulnerable code path requires sendmsg of crypto data combined with a splice from a page-cache-backed file descriptor; none of those operations occur, so the bug cannot trigger.
A successful probe means the surface is reachable. Whether the kernel still contains the bug is decided by the kernel-version + changelog signals.
Side effect: a successful bind autoloads algif_aead via the kernel module autoloader. The module check runs before the mechanism probe so the loaded-state report is pre-probe. To suppress autoload entirely, blacklist algif_aead first.
| Code | Meaning |
|---|---|
0 | PATCHED / NOT_VULNERABLE / MITIGATED / LIKELY_NOT_EXPLOITABLE |
2 | VULNERABLE or MECHANISM_REACHABLE (partial scan, kernel-version not checked) |
3 | INCONCLUSIVE (insufficient signals) |
| Distro | Detect | Kernel pkg | Notes |
|---|---|---|---|
| Ubuntu / Debian / Mint / Pop!_OS | apt | linux-image-$(uname -r) | Disk-first changelog read avoids apt changelog network fragility on signed kernels |
| RHEL / CentOS / Rocky / Alma / Fedora / Amazon Linux | rpm | kernel | Ships algif_aead built-in (CONFIG_..._AEAD=y); blacklist mitigation not effective |
| Oracle Linux | rpm | kernel or kernel-uek | UEK detected via uek substring in uname -r |
| openSUSE / SLES | rpm | kernel-default | |
| Alpine | apk | linux-lts / linux-virt / etc. | Flavor picked from release suffix |
| Arch / CachyOS / Manjaro / Endeavour / Gentoo | none | n/a | Rolling/source: relies on kernel-version check |
Auto-detects your arch, downloads the right binary into $(pwd), and verifies its SHA-256 against the published SHA256SUMS:
curl -fsSL https://copyfail.pcdoyle.dev/install.sh | sh
The script exits non-zero on checksum mismatch and removes the bad file.
Pick the binary for your host architecture:
| Architecture | Binary |
|---|---|
Intel/AMD 64-bit (x86_64) | cvecheck-linux-x86_64 |
ARM 64-bit (aarch64) | cvecheck-linux-arm64 |
Intel/AMD 32-bit (i?86) | cvecheck-linux-x86 |
Verify before running:
curl -LO https://github.com/pcdoyle/copy-fail-cve-2026-31431/releases/latest/download/cvecheck-linux-x86_64
curl -LO https://github.com/pcdoyle/copy-fail-cve-2026-31431/releases/latest/download/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
chmod +x cvecheck-linux-x86_64
make build # bin/cvecheck-linux-{x86_64,arm64,x86}
# SCP(SFTP) to Server:
scp ./bin/cvecheck-linux-x86_64 host:/tmp/ # Less than 4 MB, static, no glibc dep
# SSH:
ssh <host>
# Run Binary:
/tmp/cvecheck-linux-x86_64 # Human friendly pretty output.
/tmp/cvecheck-linux-x86_64 --format=json # Script, Syslog, and SIEM friendly
/tmp/cvecheck-linux-x86_64 --format=text # Script, and Pipe friendly
ssh <host> /tmp/cvecheck-linux-x86_64 # If run directly defaults to --format=text
ssh <host> /tmp/cvecheck-linux-x86_64 --format=json # Syslog/SIEM-friendly
Mount the host root somewhere readable and pass --root:
docker run --rm -v /:/host:ro alpine /tmp/cvecheck --root /<host-path>
--root controls all on-disk lookups (/etc/os-release, modprobe.d, /lib/modules, /boot/config-*, changelog files). The kernel-version and mechanism probes still touch the running kernel via uname(2) and socket(AF_ALG, ...).
Resolved in this order (first match wins):
PATCHED: Distro changelog references the CVE ID.NOT_VULNERABLE: Running kernel >= upstream fixed version.MITIGATED: algif_aead Blacklisted and not loaded and not built into vmlinux.LIKELY_NOT_EXPLOITABLE: AF_ALG unavailable and module not on disk.MECHANISM_REACHABLE: Surface reachable but kernel version not checked.VULNERABLE: Kernel in vuln range and mechanism reachable.INCONCLUSIVE: None of the above match.If --mechanism runs alongside --kernel-version and both signal trouble, the result is VULNERABLE with a remediation hint.
algif_aead until kernel upgrade lands.
echo 'blacklist algif_aead' | sudo tee /etc/modprobe.d/cve-2026-31431.conf
sudo rmmod algif_aead 2>/dev/null
CONFIG_CRYPTO_USER_API_AEAD=y puts the symbol inside vmlinux. Only a kernel upgrade (or kpatch-style live patch) resolves exposure. The tool detects this.| Symptom | Cause | Fix |
|---|---|---|
changelog: error="apt: exit status 100 ... Changelog unavailable for linux-signed-amd64" | Debian/Ubuntu signed kernel; apt mirror does not serve the source-pkg changelog | Error appears only when the on-disk file is missing in addition to the mirror being inaccessable, install apt-doc or wait for the mirror. |
module: ... config_src="" | No kernel config readable (no /boot/config-*, no /proc/config.gz, /boot is root-only) | Run as root, or accept that BuiltIn cannot be determined. Verdict may still resolves via other signals. |
mechanism: error="EAFNOSUPPORT" | Kernel built without CONFIG_CRYPTO_USER_API, so the host is not vulnerable via AF_ALG | Verdict will be LIKELY_NOT_EXPLOITABLE. |