← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-31431 · CWE-669 · Disclosed 2026-04-22

In the Linux kernel

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a loaded service elevator, not a front door

CVE-2026-31431 is a Linux kernel local privilege escalation in the algif_aead path behind the AF_ALG userspace crypto interface. In plain English: a low-privilege local user can abuse AEAD handling plus splice() to place a controlled 4-byte write into page cache for a readable file, then target a setuid binary and turn that transient in-memory corruption into root. Upstream exposure is broadly described as kernels since 4.17+, while vendor backports widen that in places; SUSE explicitly says 4.14+ era kernels and even some older branches with a buggy backport were affected.

The vendor's HIGH 7.8 is basically right on the math, but not on the operational urgency. This is still *post-initial-access* because it needs local code execution and low privileges, so it does not deserve a CRITICAL internet-fire score. But it is KEV-listed, publicly weaponized, reliable, tiny, and broadly applicable across enterprise Linux fleets, so defenders should treat it like a fast follow-on privilege-escalation patch, not a routine local bug.

"KEV-listed local root on Linux: not internet-wormable, but once an attacker lands, this is a near-clean path to root."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land local code execution

The attacker first needs a foothold on the target Linux host or inside a container sharing the vulnerable host kernel. That foothold can be a normal user shell, an app execution primitive, CI runner access, SSH access, or a compromised workload. The key point is that this CVE does not give initial access; it accelerates the next stage after compromise.
Conditions required:
  • Attacker has local code execution or an interactive shell
  • Attacker has at least low privileges (PR:L)
  • Target runs a vulnerable kernel build
Where this breaks in practice:
  • No unauthenticated remote path is inherent to the bug
  • Modern enterprises with strong MFA, PAM controls, and hardened container admission reduce how often attackers get this prerequisite
  • Single-purpose appliances and minimal images may not offer a practical user foothold
Detection/coverage: Network scanners will miss this stage. EDR, login telemetry, container runtime telemetry, and suspicious shell execution are the realistic controls here.
STEP 02

Abuse AF_ALG AEAD with public tooling

With a foothold, the attacker can use the public Theori/Xint research and the published copy_fail_exp.py PoC to drive the vulnerable algif_aead path. The bug is a logic flaw rather than a race, which matters because it makes exploitation unusually stable and easy to reproduce across distributions.
Conditions required:
  • AF_ALG interface is present and reachable
  • algif_aead is built-in or loadable and not blocked
  • Attacker can execute normal userspace syscalls including socket() and splice()
Where this breaks in practice:
  • Hosts that explicitly disable algif_aead or AF_ALG break the exploit chain
  • Some stripped-down workloads never expose the needed interface because of custom kernels or vendor hardening
  • Container sandboxes with aggressive seccomp/LSM policy may constrain the syscall path in some environments
Detection/coverage: Version-based scanners can flag candidate kernels, but exploit-attempt detection is weaker. eBPF, auditd, or LSM telemetry around AF_ALG socket creation and unusual splice() usage provides better visibility than generic vuln scanning.
STEP 03

Overwrite page cache for a readable setuid target

The exploit turns the bug into a controlled 4-byte write against page cache for a readable file. Because the page is not marked dirty, the underlying file on disk stays unchanged, which helps the attacker sidestep file integrity checks that only inspect the filesystem object rather than live cached memory.
Conditions required:
  • A readable target file exists in page cache path
  • A practical setuid root binary is present
  • Kernel behavior matches vulnerable copy path
Where this breaks in practice:
  • Some hardened images reduce available setuid surface
  • Custom integrity monitoring that also inspects runtime behavior may still catch the follow-on execution
  • Very locked-down container images may limit useful local targets even if host escape remains a concern
Detection/coverage: Traditional file-integrity tools are weak here because disk contents may remain unchanged. Focus on anomalous execution of setuid binaries, suspicious parent-child chains, and short-lived privilege transitions.
STEP 04

Execute the tainted binary and take root

The attacker runs the now-corrupted setuid binary from page cache and pivots to root on the host or, in some architectures, from container to host context. Once root is obtained, this stops being a crypto bug and becomes a full host-trust problem: credential theft, agent tampering, kernel persistence, and lateral movement all become possible.
Conditions required:
  • Attacker can execute the chosen setuid target
  • Exploit completes before page cache state changes
  • No control blocks privileged execution
Where this breaks in practice:
  • EDR or strong audit policy may catch the final privilege transition
  • Some containerized deployments keep blast radius to one node rather than the entire cluster
  • Virtualization contains impact to the guest; this is not a hypervisor escape by itself
Detection/coverage: This is the best place to catch it operationally: alert on non-admin accounts spawning su, odd setuid execution paths, unexpected UID 0 transitions, or container processes crossing into host-level administration.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusYes. NVD marks the CVE as present in CISA KEV, which means confirmed exploitation in the wild.
KEV statusListed by CISA KEV on 2026-05-01 with due date 2026-05-15 per the NVD KEV section.
PoC availabilityPublic and mature. Theori published copy_fail_exp.py in theori-io/copy-fail-CVE-2026-31431; CERT/CC also notes a public PoC.
EPSS0.02235 from the user-provided intel. Percentile was not independently confirmed in the sources reviewed.
CVSS vectorCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — translation: *easy local post-compromise root*, not pre-auth remote.
Affected versionsBroad exposure across Linux. CERT/CC describes kernel 4.17 and later; SUSE says 4.14 and newer across many products and notes some older branches were affected by backport behavior.
Fixed versionsUpstream/stable backports appear in branches such as 6.18.22, 6.19.12, and 7.0.10; Debian lists fixes including bullseye 5.10.257-1, bookworm 6.1.174-1, trixie 6.12.90-2, sid 7.0.10-1. Ubuntu and Red Hat shipped distro backports rather than requiring those exact upstream numbers.
Exposure / scanning realityNot internet-scannable in any meaningful sense. Shodan/Censys-style exposure counts are not the right model here because the exploit requires local execution. What matters is fleet population of vulnerable kernels, shared multi-user hosts, CI runners, and container nodes.
Timeline clarityUse two dates: the CVE record was published 2026-04-22, while CERT/CC and public exploit discussion point to public exploitation details on 2026-04-29.
Researcher / disclosureDiscovered by Taeyang Lee of Theori, with CERT/CC crediting assistance from Theori's AI-based analysis tool Xint Code.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (8.4/10)

The decisive factor is that this bug is post-initial-access: the attacker already needs local execution and low privileges before the exploit even starts. KEV listing and a highly reliable public exploit keep it firmly in HIGH, but those facts do not erase the attacker-position requirement that prevents a CRITICAL rating.

HIGH KEV-listed active exploitation and public exploit availability
HIGH Privilege-escalation impact once local access exists
MEDIUM Cross-distro fixed-version granularity because of heavy vendor backporting

Why this verdict

  • KEV changes urgency, not attack position — CISA KEV means real-world abuse is happening, so this cannot be treated as a theoretical local bug.
  • Exploit friction is unusually low — the public Theori PoC is tiny, the bug is logic-based rather than race-based, and multiple sources describe it as broadly reliable across major distros.
  • The reachable population is narrowed by attacker position — it requires local execution and low privileges, which implies the adversary already has a foothold or a hostile workload on the box; that is meaningful downward pressure from CRITICAL.
  • Blast radius is host-level and serious — once exploited, the attacker gets root, can tamper with agents and credentials, and can potentially turn container footholds into node compromise.
  • Enterprise prevalence keeps the score high — Linux servers, CI runners, jump boxes, Kubernetes nodes, and shared utility hosts make the affected population too large to dismiss as niche.

Why not higher?

This is not an unauthenticated remote exploit and it is not a wormable perimeter event. The attacker must already be on the host or in a relevant container context with low privileges, which means the CVE is a privilege-escalation accelerator rather than an initial-access primitive. That prerequisite is the main reason it stops at HIGH.

Why not lower?

Dropping this to MEDIUM would ignore two real-world amplifiers: KEV-listed exploitation and a public, reliable PoC. On a 10,000-host fleet, any bug that turns ordinary user access into root across common Linux builds deserves fast action, even if it is technically 'local only.'

05 · Compensating Control

What to do — in priority order.

  1. Disable algif_aead immediately — If your distro supports module blocking, prevent algif_aead from loading or unload it where safe. Because this CVE is KEV-listed, deploy this mitigation immediately, within hours, not on a normal 30-day HIGH clock.
  2. Block AF_ALG init paths on systems that cannot reboot yet — On platforms like Red Hat where the function may be built-in, use the vendor-documented initcall_blacklist=algif_aead_init or initcall_blacklist=af_alg_init workaround where operationally acceptable. This is your stopgap for high-value hosts that cannot take a kernel patch today; again, do it within hours because of active exploitation.
  3. Prioritize multi-tenant Linux first — Patch shared bastions, CI runners, jump hosts, VDI-backed Linux, Kubernetes nodes, and any box where untrusted users or workloads can execute code before single-user appliances. These are the systems where the local-access prerequisite is easiest to satisfy, so they get the first emergency wave within hours.
  4. Tighten container and shell access — Reduce low-privilege footholds while patching: restrict oc debug/cluster-admin pathways, keep SELinux enforcing, avoid running workloads as root, and review SSH/user access on sensitive nodes. These are compensating controls only, but they meaningfully cut exploitability during the patch window and should be applied within hours on internet-adjacent or shared systems.
  5. Monitor AF_ALG and anomalous setuid execution — Add temporary detections for AF_ALG socket creation, unusual splice() usage, and unexpected setuid root binary launches by non-admin accounts. This will not prevent exploitation by itself, but it improves odds of catching live abuse while your fleet rollout proceeds; stand it up within hours where telemetry exists.
What doesn't work
  • A WAF does nothing here because there is no native web attack surface in the vulnerability.
  • External attack-surface management will not find this because the exploit path is local, not internet-exposed.
  • Filesystem integrity checks alone are weak because the exploit targets page cache and the underlying file may remain unchanged on disk.
  • Secure Boot does not stop runtime exploitation of a vulnerable, already-booted kernel.
  • Assuming containers contain it is unsafe; the bug can turn a container foothold into a node-level problem depending on workload and host policy.
06 · Verification

Crowdsourced verification payload.

Run this on the target Linux host, not from an auditor workstation. Invoke it as sudo bash ./check-copy-fail.sh; root is recommended so the script can read kernel boot args, module state, and package metadata. The script is conservative: it returns PATCHED when it sees a known mitigation or a known fixed package/kernel on supported Debian/Ubuntu paths, VULNERABLE when it sees a known affected state, and UNKNOWN when vendor backporting prevents a reliable offline verdict.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-copy-fail.sh
# Conservative host-side checker for CVE-2026-31431 (Copy Fail)
# Outputs exactly one of: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -u

KREL="$(uname -r 2>/dev/null || true)"
OS_ID=""
OS_VER=""
CODENAME=""
CMDLINE="$(cat /proc/cmdline 2>/dev/null || true)"

if [ -r /etc/os-release ]; then
  # shellcheck disable=SC1091
  . /etc/os-release
  OS_ID="${ID:-}"
  OS_VER="${VERSION_ID:-}"
  CODENAME="${VERSION_CODENAME:-}"
fi

have_cmd() { command -v "$1" >/dev/null 2>&1; }

ver_ge() {
  # returns 0 if $1 >= $2 using sort -V
  [ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | tail -n1)" = "$1" ]
}

patched() {
  echo "PATCHED"
  exit 0
}

vulnerable() {
  echo "VULNERABLE"
  exit 1
}

unknown() {
  echo "UNKNOWN"
  exit 2
}

# 1) Strong mitigation signals from vendor guidance
if printf '%s' "$CMDLINE" | grep -Eq '(^| )initcall_blacklist=(algif_aead_init|af_alg_init)( |$)'; then
  patched
fi

if grep -RqsE '^\s*install\s+algif_aead\s+/bin/false\s*$' /etc/modprobe.d /usr/lib/modprobe.d 2>/dev/null; then
  patched
fi

# 2) Ubuntu kmod mitigation versions from Ubuntu USN/blog
if [ "$OS_ID" = "ubuntu" ] && have_cmd dpkg-query; then
  KMOD_VER="$(dpkg-query -W -f='${Version}' kmod 2>/dev/null || true)"
  case "$OS_VER" in
    22.04)
      [ -n "$KMOD_VER" ] && dpkg --compare-versions "$KMOD_VER" ge "29-1ubuntu1.1" && patched
      ;;
    24.04)
      [ -n "$KMOD_VER" ] && dpkg --compare-versions "$KMOD_VER" ge "31+20240202-2ubuntu7.2" && patched
      ;;
    25.10)
      [ -n "$KMOD_VER" ] && dpkg --compare-versions "$KMOD_VER" ge "34.2-2ubuntu1.1" && patched
      ;;
  esac
fi

# 3) Ubuntu generic kernel fixed versions from Ubuntu CVE page
if [ "$OS_ID" = "ubuntu" ]; then
  case "$OS_VER" in
    26.04) patched ;;
    25.10)
      case "$KREL" in
        6.17.0-*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "6.17.0-29.29" && patched || vulnerable
          ;;
      esac
      ;;
    24.04)
      case "$KREL" in
        6.8.0-*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "6.8.0-117.117" && patched || vulnerable
          ;;
      esac
      ;;
    22.04)
      case "$KREL" in
        5.15.0-*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "5.15.0-179.189" && patched || vulnerable
          ;;
      esac
      ;;
    20.04)
      case "$KREL" in
        5.4.0-*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "5.4.0-230.250" && patched || vulnerable
          ;;
      esac
      ;;
    18.04)
      case "$KREL" in
        4.15.0-*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "4.15.0-250.262" && patched || vulnerable
          ;;
      esac
      ;;
    16.04|14.04)
      # Generic Ubuntu releases are not broadly affected; 4.15 HWE cases are special.
      case "$KREL" in
        4.15.*) unknown ;;
        *) patched ;;
      esac
      ;;
  esac
fi

# 4) Debian package/kernel checks from Debian security tracker
if [ "$OS_ID" = "debian" ]; then
  case "$CODENAME" in
    bullseye)
      case "$KREL" in
        5.10.*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "5.10.257" && patched || vulnerable
          ;;
        6.1.*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "6.1.174" && patched || vulnerable
          ;;
      esac
      ;;
    bookworm)
      case "$KREL" in
        6.1.*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "6.1.174" && patched || vulnerable
          ;;
      esac
      ;;
    trixie)
      case "$KREL" in
        6.12.*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "6.12.90" && patched || vulnerable
          ;;
        7.0.*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "7.0.9" && patched || vulnerable
          ;;
      esac
      ;;
    forky)
      case "$KREL" in
        7.0.*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "7.0.9" && patched || vulnerable
          ;;
      esac
      ;;
    sid|unstable)
      case "$KREL" in
        6.19.*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "6.19.12" && patched || vulnerable
          ;;
        7.0.*)
          BASE="${KREL%%[^0-9.-]*}"
          ver_ge "$BASE" "7.0.10" && patched || vulnerable
          ;;
      esac
      ;;
  esac
fi

# 5) Generic upstream heuristics only where backporting ambiguity is low
# If algif_aead is absent/blocked, exposure is materially reduced.
if ! grep -q '^algif_aead ' /proc/modules 2>/dev/null; then
  if ! have_cmd modprobe || ! modprobe -n -v algif_aead >/dev/null 2>&1; then
    # Could be built-in or truly absent; do not overclaim.
    unknown
  fi
fi

# Upstream stable branches called out by advisories.
case "$KREL" in
  6.18.*)
    BASE="${KREL%%[^0-9.-]*}"
    ver_ge "$BASE" "6.18.22" && patched || vulnerable
    ;;
  6.19.*)
    BASE="${KREL%%[^0-9.-]*}"
    ver_ge "$BASE" "6.19.12" && patched || vulnerable
    ;;
  7.0.*)
    BASE="${KREL%%[^0-9.-]*}"
    ver_ge "$BASE" "7.0.10" && patched || vulnerable
    ;;
  4.*|5.*|6.*)
    # Heavy distro backporting makes a universal offline answer unsafe.
    unknown
    ;;
  *)
    unknown
    ;;
esac
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, treat this as a post-compromise root enabler with active exploitation. For hosts that can take an emergency change, use the KEV override and patch or mitigate immediately, within hours by disabling algif_aead/AF_ALG where the vendor supports it, starting with shared Linux servers, CI runners, bastions, and Kubernetes nodes; that is your noisgate mitigation SLA here. For the permanent fix, roll the vendor kernel update on an accelerated basis and do not hide behind the ordinary HIGH window just because the noisgate remediation SLA is <= 180 days—KEV means this belongs in the current emergency kernel wave, not the backlog.

Sources

  1. NVD CVE-2026-31431
  2. CERT/CC VU#260001
  3. Red Hat RHSB-2026-002
  4. Debian security tracker CVE-2026-31431
  5. Ubuntu CVE page
  6. Ubuntu Copy Fail fixes blog
  7. SUSE response to Copy Fail
  8. Theori public PoC repository
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.