This is a trapdoor hidden behind two locked doors and a badge reader
CVE-2026-31413 is a Linux kernel eBPF verifier soundness bug in maybe_fork_scalars() for BPF_OR. A crafted BPF program can make the verifier believe a scalar is safely bounded when runtime behavior differs, creating verifier/runtime divergence that can lead to out-of-bounds map access. Upstream affected ranges published by NVD are 6.12.75 to <6.12.80, 6.18.16 to <6.18.21, and 6.19.6 to <6.19.11; the mainline fix landed as commit c845894ebd6f... in 7.0-rc5.
The vendor's 7.8/HIGH score is technically understandable because successful exploitation can end in full local privilege escalation. In the real world, though, this is usually *post-initial-access* and often *post-policy-bypass*: the attacker needs a local foothold and a path to load a crafted BPF program, while many enterprise kernels gate unprivileged bpf() behind unprivileged_bpf_disabled or require CAP_BPF/CAP_SYS_ADMIN. Add the narrow affected version windows and the fact that major maintained Ubuntu and Debian releases are marked not affected, and this drops out of urgent fleet-wide patch-now territory.
4 steps from start to impact.
Land local code execution on a Linux host
bpf() syscall.- Local execution on the target host or container
- Target runs an affected upstream kernel range or a vulnerable vendor backport
- Requires prior compromise or an insider position
- Many enterprise endpoints and servers will never expose this path to an external attacker
Reach BPF program loading with bpftool/libbpf semantics
BPF_OR. The practical loader can be custom code using bpf(2), or tooling built on libbpf/bpftool behavior, but the critical prerequisite is that the kernel actually permits the caller to submit the program for verification.- Unprivileged
bpf()allowed, or attacker hasCAP_BPF/CAP_SYS_ADMIN - No seccomp/AppArmor/SELinux/container policy blocking the needed syscall path
- Many distributions and hardened fleets set
/proc/sys/kernel/unprivileged_bpf_disabled - Default container policies often strip capabilities and may block dangerous syscall patterns
bpf() attempts and reads of /proc/sys/kernel/unprivileged_bpf_disabled; few scanners assess this reliably at scale.Trigger verifier/runtime divergence
maybe_fork_scalars() so the verifier tracks one value while runtime evaluates another. That mismatch can permit out-of-bounds map access even though the verifier accepted the program. This is a classic 'verifier says safe, runtime says not actually' kernel bug.- Exploit author can craft the exact BPF instruction sequence
- Kernel includes the vulnerable verifier logic
- No public GitHub PoC was readily discoverable at assessment time
- Verifier bugs are brittle across versions and often require per-kernel validation
Escalate impact on the host
- Successful exploitation of the map access primitive
- Valuable host privileges or adjacent workloads exist on the node
- Impact stays local to the host; there is no wormable or remote fan-out built into the bug
- Some workloads run on kernels or distro backports already marked not affected
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found during this assessment; not listed in CISA KEV as checked against the public catalog. |
|---|---|
| Public PoC availability | No obvious public GitHub PoC located for CVE-2026-31413; exploitation appears to require custom eBPF program construction rather than copy-paste tradecraft. |
| EPSS | 0.00011 from the user-provided intel block; that is effectively negligible modeled near-term exploitation probability. |
| KEV status | No; no CISA Known Exploited Vulnerabilities listing located as of 2026-05-23. |
| CVSS vector | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — this is a *local*, low-privilege, no-user-interaction kernel LPE profile, not a remote edge-service problem. |
| Affected versions | NVD lists upstream Linux kernel ranges 6.12.75 to <6.12.80, 6.18.16 to <6.18.21, and 6.19.6 to <6.19.11. |
| Fixed versions | Upstream stable fixes are 6.12.80, 6.18.21, and 6.19.11; Debian notes the fix commit as c845894ebd6f... in 7.0-rc5 and shows maintained bullseye, bookworm, and trixie as not affected. |
| Distro posture | Canonical marks maintained Ubuntu releases shown on the advisory page as Not affected. Debian tracker also marks the maintained branches in the notes as not affected, despite package bookkeeping showing later fixed uploads. |
| Exposure/scanning reality | There is no meaningful Shodan/Censys/GreyNoise internet fingerprint for this bug because it is a local verifier flaw, not a remotely queryable network service. Fleet exposure is driven by host kernel version and BPF policy, not by open ports. |
| Disclosure | Publicly disclosed 2026-04-12 by kernel.org; NVD last modified 2026-05-20 with affected CPE ranges. |
noisgate verdict.
The decisive downgrade factor is reachability: exploitation depends on local execution *and* a viable path to load a crafted BPF program, which many enterprise fleets intentionally block. This is still a real kernel LPE when those controls are absent, but it is not a broad internet-scale emergency and the affected version population is unusually narrow.
Why this verdict
- Local-only attack surface: start from vendor 7.8/HIGH, then cut down because
AV:Lmeans this is already post-initial-access. - BPF gate is the real choke point: practical exploitation usually requires unprivileged
bpf()to be enabled or the attacker to already holdCAP_BPF/CAP_SYS_ADMIN; that is a strong downward adjustment in hardened fleets. - Narrow affected population: NVD's affected windows are recent and specific, and maintained Ubuntu plus maintained Debian branches shown by their trackers are marked not affected, which materially shrinks blast radius.
Why not higher?
There is no KEV listing, no public exploitation evidence found, and no straightforward remote entry point. The exploit chain compounds on two prerequisites that slash the reachable population: prior local foothold and BPF program-loading reachability.
Why not lower?
If an attacker can submit crafted BPF bytecode on a vulnerable host, the impact is kernel-level and severe. On developer workstations, observability-heavy servers, or permissive container nodes where BPF access exists, this can still become a clean host-level privilege escalation.
What to do — in priority order.
- Disable unprivileged BPF — Set
/proc/sys/kernel/unprivileged_bpf_disabled=1or your distro's persistent equivalent where operationally safe. This directly attacks the main exploit precondition and, for a MEDIUM noisgate verdict, there is no mitigation SLA — go straight to the remediation window unless your environment intentionally exposes BPF to low-privilege users. - Constrain container capabilities — Strip
CAP_BPF,CAP_SYS_ADMIN, and adjacent high-risk capabilities from containers and node agents that do not absolutely need them. This matters most on Kubernetes and shared Linux nodes, and should be folded into your next normal hardening change before the 365-day remediation window closes. - Audit seccomp and syscall policy — Confirm that container runtimes and sandbox profiles do not unnecessarily permit dangerous syscall reach for untrusted workloads. This does not replace patching, but it reduces the chance that a compromised container can exercise the verifier path before you remediate.
- Hunt for BPF loader usage — Collect telemetry on unexpected
bpf()activity,bpftoolusage, and reads/writes to/proc/sys/kernel/unprivileged_bpf_disabled. Use that as a targeted threat hunt on engineering hosts and Kubernetes nodes during the remediation window.
- Perimeter controls and WAFs do not help; this is not a remotely reachable network-service bug.
- File integrity monitoring does not prevent the exploit path; the issue lives in kernel verifier logic, not a changed binary on disk.
- Version-only internet exposure scanning is misleading here; open ports tell you almost nothing about whether a host can be exploited via BPF.
Crowdsourced verification payload.
Run this on the target Linux host as root or with enough privilege to read /proc/sys/kernel/unprivileged_bpf_disabled; example: sudo bash ./check-cve-2026-31413.sh. It checks the running kernel release against the upstream vulnerable ranges and reports whether unprivileged BPF is enabled, but it intentionally returns UNKNOWN for vendor-backported kernels it cannot confidently map.
#!/usr/bin/env bash
# check-cve-2026-31413.sh
# Determine likely exposure to CVE-2026-31413 on the running Linux host.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
rel="$(uname -r 2>/dev/null)"
base="${rel%%-*}"
status="UNKNOWN"
reason="Unable to map running kernel to upstream affected ranges"
ver_ge() {
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
}
ver_lt() {
[ "$1" != "$2" ] && [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}
in_range() {
local v="$1" lo="$2" hi="$3"
ver_ge "$v" "$lo" && ver_lt "$v" "$hi"
}
# Upstream NVD ranges.
if in_range "$base" "6.12.75" "6.12.80" || in_range "$base" "6.18.16" "6.18.21" || in_range "$base" "6.19.6" "6.19.11"; then
status="VULNERABLE"
reason="Running kernel version falls inside upstream affected ranges"
else
# Ubuntu maintained releases are marked not affected in the vendor advisory.
if [ -r /etc/os-release ]; then
. /etc/os-release
case "${ID:-}" in
ubuntu)
status="PATCHED"
reason="Ubuntu advisory marks maintained releases shown there as Not affected"
;;
debian)
# Debian tracker marks maintained bullseye/bookworm/trixie branches not affected,
# but package naming/backports can be ambiguous from uname alone.
if [ "$status" = "UNKNOWN" ]; then
reason="Debian requires package-level validation; tracker marks maintained branches not affected"
fi
;;
esac
fi
# If upstream version is equal to or newer than the published fixes and not distro-modified,
# we can call it patched with high confidence.
if [ "$status" = "UNKNOWN" ] && [[ "$rel" != *-* ]]; then
if ver_ge "$base" "6.19.11"; then
status="PATCHED"
reason="Mainline/stable kernel is at or beyond an upstream fixed version"
elif ver_ge "$base" "6.18.21" && ver_lt "$base" "6.19.0"; then
status="PATCHED"
reason="6.18 stable kernel is at or beyond upstream fixed version"
elif ver_ge "$base" "6.12.80" && ver_lt "$base" "6.13.0"; then
status="PATCHED"
reason="6.12 stable kernel is at or beyond upstream fixed version"
fi
fi
fi
bpf_gate="unknown"
if [ -r /proc/sys/kernel/unprivileged_bpf_disabled ]; then
bpf_gate="$(cat /proc/sys/kernel/unprivileged_bpf_disabled 2>/dev/null)"
fi
printf 'Kernel release: %s\n' "$rel"
printf 'Base version: %s\n' "$base"
printf 'unprivileged_bpf_disabled: %s\n' "$bpf_gate"
printf 'Assessment reason: %s\n' "$reason"
case "$status" in
VULNERABLE)
if [ "$bpf_gate" = "1" ] || [ "$bpf_gate" = "2" ]; then
printf 'VULNERABLE\n'
exit 1
else
printf 'VULNERABLE\n'
exit 1
fi
;;
PATCHED)
printf 'PATCHED\n'
exit 0
;;
*)
printf 'UNKNOWN\n'
exit 2
;;
esac
If you remember one thing.
6.12.75-6.12.79, 6.18.16-6.18.20, or 6.19.6-6.19.10, then intersect that with systems where unprivileged BPF is enabled or workloads carry CAP_BPF/CAP_SYS_ADMIN. For a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window, but if you find exposed BPF on shared nodes, disable unprivileged BPF as a hardening control now and complete vendor kernel remediation within the noisgate remediation SLA of 365 days.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.