Someone left the back door of the bank vault propped open with a sticky note that says 'ARP rewrite here'
CVE-2026-53266 is an out-of-bounds write (CWE-787) in the Linux kernel's netfilter bridge ebt_snat module. When the ebtables SNAT target rewrites the ARP sender hardware address, it calls skb_store_bits() without first calling skb_ensure_writable() on the ARP SHA range. If that range sits in a nonlinear skb fragment backed by a splice-imported file page, the write goes directly into page-cache memory — corrupting file contents, violating process memory isolation, or clobbering adjacent kernel heap objects. The flaw affects kernels from 5.4.73 through 7.0.12 across every stable branch: 5.10.x (fixed in 5.10.259), 5.15.x (5.15.210), 6.1.x (6.1.176), 6.6.x (6.6.143), 6.12.x (6.12.94), and 6.18.x (6.18.36). Every major enterprise distro — RHEL 8/9/10, Debian bullseye through sid, Amazon Linux 2023, SUSE, Ubuntu — shipped vulnerable kernels for months before backports landed. The fix commit is 67ba971ae025.
The vendor CNA scored this HIGH 8.8 (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) with a Scope change reflecting the ability to affect resources beyond the vulnerable component — namely, container escape. Red Hat scored it lower at 7.5, citing the bridge-netfilter configuration prerequisite. Both undercount the real-world severity. The Scope:Changed flag is doing heavy lifting here because it captures what actually happens: an attacker inside a container can obtain CAP_NET_ADMIN via an unprivileged user namespace (enabled by default on Ubuntu, Fedora, and most cloud-optimized kernels), create a bridge, install ebtables SNAT rules, and trigger the OOB write to escape the container entirely. CISA added this to the KEV catalog on 2026-09-18, confirming active exploitation in coordinated cloud workload attacks alongside CVE-2025-39964 and CVE-2025-39682. The vendor's HIGH does not adequately reflect the fleet-scale blast radius on container infrastructure.
6 steps from start to impact.
Gain code execution inside a container or as an unprivileged user
- Code execution inside a container or as an unprivileged local user on a Linux host running a vulnerable kernel (5.4.73 – 7.0.12)
- Requires a separate initial-access vulnerability or credential compromise — this CVE is not initial access
Obtain CAP_NET_ADMIN via unprivileged user namespace
unshare(CLONE_NEWUSER | CLONE_NEWNET) to create a new user namespace and network namespace. Inside the user namespace, the attacker has full CAP_NET_ADMIN. On Ubuntu (all versions through 24.04 without explicit restriction), Fedora, and most cloud-optimized kernels, unprivileged user namespaces are enabled by default. This requires zero additional privileges beyond a shell.- Unprivileged user namespaces enabled (sysctl
kernel.unprivileged_userns_clone=1oruser.max_user_namespaces > 0)
- RHEL 9+ and hardened environments may restrict unprivileged user namespace creation via sysctl or SELinux policy
- Ubuntu 24.04+ introduced
apparmor_restrict_unprivileged_usernsbut bypass techniques have been published (oss-security, 2025-Q1)
unshare and clone syscalls with namespace flags; monitor for new network namespace creation from non-root processes.Create bridge interface and install ebtables SNAT ARP rewrite rule
CAP_NET_ADMIN in the new namespace, the attacker creates a bridge interface (brctl addbr or ip link add type bridge), loads the ebt_snat kernel module if not already loaded, and installs an ebtables rule targeting ARP traffic with the --snat-arp flag. This sets up the vulnerable code path in net/bridge/netfilter/ebt_snat.c.- CAP_NET_ADMIN in a network namespace
- The
ebt_snatmodule must be loadable (not blacklisted)
- Systems with
CONFIG_BRIDGE_NF_EBTABLES=nor the module blacklisted are not reachable - Seccomp profiles that block
setsockopt(SO_SET_REPLACE)orioctlfor ebtables prevent rule installation
modprobe ebt_snat and audit ebtables rule changes via kernel audit subsystem (-a always,exit -F arch=b64 -S setsockopt).Craft nonlinear skb via splice and trigger ARP traffic through the bridge
splice() to import a file page into a socket buffer, creating a nonlinear skb where the ARP payload resides in a paged fragment backed by file-mapped memory. The attacker then sends a crafted ARP packet through the bridge interface. When the ebtables SNAT rule fires, skb_store_bits() writes the new MAC address directly into the file-backed page without the skb_ensure_writable() check.- Ability to call
splice()and send packets through the bridge - The ARP payload range must be in a nonlinear fragment (achieved by the splice import)
- Reliable triggering requires understanding of skb internals and splice-backed fragment layout
- Seccomp profiles blocking
spliceprevent this path
ebt_snat. Monitor for kernel oops or KASAN splats in dmesg.Corrupt kernel heap objects or file-backed pages for privilege escalation
msg_msg spray), the attacker shapes the heap so the write corrupts a target object — such as a cred struct, task_struct, or pipe buffer — to escalate to root. Alternatively, corrupting file-backed pages can modify setuid binaries or /etc/shadow on disk. On container hosts, root in the initial namespace means full host compromise.- Successful heap layout manipulation
- Knowledge of target kernel slab allocator layout for the running kernel version
- Heap grooming is kernel-version-specific and fragile — exploit reliability varies across distro kernels
- SLAB randomization and
CONFIG_SLAB_FREELIST_HARDENEDincrease grooming difficulty
cred structure modifications. Post-exploitation lateral movement triggers standard EDR/NDR alerts.Container escape and lateral movement
- Root access on the container host
- Container runtime socket or kubelet credentials accessible
- Kubernetes nodes with Pod Security Standards (restricted) limit post-escape impact
- Network policies and service mesh mTLS limit lateral movement
sysctl kernel.unprivileged_userns_clone=0 (Debian/Ubuntu) or sysctl user.max_user_namespaces=0 (RHEL/Fedora) and persist in /etc/sysctl.d/. This breaks the attacker's ability to obtain CAP_NET_ADMIN from an unprivileged position, collapsing step 2 of the attack chain entirely. On Ubuntu 24.04+, also set kernel.apparmor_restrict_unprivileged_userns=1. Deploy within 3 days per the noisgate mitigation SLA for CRITICAL. Note: this may break Flatpak, Podman rootless, Chrome sandboxing, and other namespace-dependent userspace — test on a canary group first.blacklist ebt_snat and install ebt_snat /bin/false to /etc/modprobe.d/cve-2026-53266.conf, then run rmmod ebt_snat if loaded. This prevents the vulnerable code path from being reached even if the attacker has CAP_NET_ADMIN. Deploy within 3 days. Warning: this breaks any bridge NAT rules using ebtables SNAT — audit your bridge configurations first. Container networking typically uses iptables/nftables NAT, not ebtables SNAT, so impact is usually nil.unshare, clone with namespace flags, and splice syscalls for workloads that don't need them. Kubernetes Pod Security Standards 'restricted' profile blocks most namespace operations. This breaks steps 2 and 4 of the attack chain. Deploy within 3 days. Ensure your container orchestrator applies profiles by default — Kubernetes does NOT enforce seccomp unless explicitly configured via securityContext.seccompProfile.kpatch for temporary live patching where available, but a reboot is still needed for full remediation. Per the noisgate remediation SLA for CRITICAL, complete patching and rebooting across the fleet within 90 days. Given KEV status, prioritize container hosts and hypervisors for immediate reboot windows.- Network firewalls / WAFs — This is a local privilege escalation, not a network attack. No amount of perimeter filtering addresses this vulnerability.
- SELinux / AppArmor in default policy — Default SELinux targeted policy on RHEL does not restrict user namespace creation or ebtables rule installation for confined processes. AppArmor's namespace restriction on Ubuntu 24.04 has published bypasses. These provide defense-in-depth but are not reliable standalone mitigations.
- Container image scanning (Trivy, Grype) — These scan container images for vulnerabilities in userspace packages. A host kernel vulnerability is invisible to image scanners. You need authenticated host-level vulnerability scanning.
- Kubernetes NetworkPolicy — Controls pod-to-pod traffic, not kernel syscall behavior. Does not prevent the local exploitation chain.
The supporting signals.
| In-the-Wild Exploitation | Confirmed. CISA added CVE-2026-53266 to the KEV catalog on 2026-09-18. Observed in coordinated campaigns targeting cloud workloads alongside CVE-2025-39964 and CVE-2025-39682 for container escape and lateral movement. |
|---|---|
| Proof of Concept | No public weaponized PoC. The suominen/CVE-2026-53266 GitHub repo is a distro patch-status tracker (CC BY 4.0), not an exploit. No PoC found on pocindex.io, ExploitDB, or Metasploit. The exploitation technique (splice-backed skb + ebtables SNAT + heap grooming) requires significant kernel internals knowledge, but the primitives are well-documented in kernel exploitation literature. |
| EPSS | 0.83% probability of exploitation in next 30 days (user-provided). This is moderate for a local kernel vuln, but the KEV listing renders EPSS moot for prioritization — known exploitation overrides prediction. |
| CVSS Vector | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H = 8.8 HIGH (CNA). The S:C (Scope Changed) flag is critical — it captures the container escape scenario where the attacker affects resources beyond the vulnerable component. Red Hat scored 7.5 without scope change. |
| Affected Versions | Linux kernel 5.4.73 through 7.0.12 across all stable branches. Introduced by commit that added ARP SHA rewrite to ebt_snat. Every major enterprise kernel shipped vulnerable for months. |
| Fixed Versions | Upstream: 5.10.259, 5.15.210, 6.1.176, 6.6.143, 6.12.94, 6.18.36, 7.1-rc7+. RHEL: 8 (4.18.0-553.144), 9 (5.14.0-687.24.1), 10 (6.12.0-211.60.1). Debian: bookworm (6.1.176-1), trixie (6.12.94-1). Amazon Linux 2023: 6.1.176-220.358. Requires reboot — installing the package alone provides zero protection. |
| Scanning & Exposure | This is a local kernel vulnerability — not directly scannable via network. Vulnerability scanners (Qualys, Tenable, Rapid7) detect via authenticated kernel version checks. No Shodan/GreyNoise/Censys exposure surface since the attack vector is local, not network-facing. |
| Disclosure Timeline | 2026-06-25: CVE published and upstream fix merged. July–August 2026: Distro backports begin shipping. 2026-09-18: CISA KEV listing with 3-day remediation deadline for exposed federal assets. 2026-09-21: Federal BOD 26-04 deadline expired. |
| Researcher / Reporter | Upstream kernel commit by the netfilter maintainers. No individual researcher publicly credited. CISA has not attributed the in-the-wild exploitation to a specific threat actor or campaign. |
| Related CVEs | Exploited in tandem with CVE-2025-39964 and CVE-2025-39682 (both Linux kernel) in coordinated cloud workload attacks. The ebtables/netfilter attack surface has a long history: see CVE-2023-32233 (nf_tables use-after-free), CVE-2022-32250 (nf_tables heap overflow). |
Sources.
Why this verdict
- KEV + active exploitation override: CISA confirmed in-the-wild exploitation on 2026-09-18. Campaigns are targeting containerized cloud workloads using this CVE alongside two others for coordinated privilege escalation and container escape. Active exploitation alone mandates immediate action regardless of friction analysis.
- User namespace collapses the privilege barrier: The CVSS vector lists PR:L (low privileges), but in practice the
CAP_NET_ADMINrequirement is trivially satisfiable on Ubuntu, Fedora, and most cloud-optimized kernels via unprivileged user namespaces (unshare -Urn). The attacker needs nothing beyond a shell inside a container. Ubuntu's 24.04 AppArmor restriction has published bypasses (oss-security 2025-Q1). This is functionally a zero-privilege prerequisite on ≥60% of enterprise Linux deployments. - Scope:Changed = container escape is the designed outcome: The S:C flag in the CVSS vector is not theoretical. The entire attack chain — user namespace → bridge → ebtables SNAT → OOB write → heap corruption → root — has been exercised in production by real threat actors. Root on a container host means access to all co-located workloads, kubelet credentials, and the container runtime socket.
- Role multiplier: Container hosts (Kubernetes nodes, Docker hosts) — The documented chain succeeds fully on container hosts, which represent ≥30% of enterprise Linux server installs (Datadog 2026 Container Report). Blast radius: container escape → host root → kubelet creds → cluster-wide lateral movement → fleet-scale compromise. The Linux kernel IS the container isolation boundary; the bug is IN that boundary. This places the verdict floor at CRITICAL per the canonical high-value-role rule.
- Role multiplier: KVM hypervisor hosts — On KVM hosts, kernel root = hypervisor compromise → access to all guest VMs. The chain succeeds identically. This is another fleet-scale outcome for ≥5% of the installed base.
- Role multiplier: CI/CD build hosts — Root on a self-hosted GitHub Actions runner, GitLab Runner, or Jenkins agent → supply-chain pivot via artifact tampering. The chain succeeds wherever containers run, which is the default for modern CI/CD.
- Bridge netfilter is not exotic friction: Container runtimes (Docker, containerd, CRI-O) load bridge netfilter modules by default for container networking. The
ebt_snatmodule is auto-loaded when the attacker installs ebtables rules withCAP_NET_ADMIN. On container hosts, the prerequisite is met by the platform's own architecture.
Why not higher?
A score above 9.0 would imply near-zero friction and remote exploitability. This CVE requires local access (it is not an initial-access vector), and the heap grooming for reliable exploitation is kernel-version-specific, reducing weaponization reliability across diverse kernel builds. The absence of a public PoC means the exploitation barrier, while clearly surmountable by sophisticated actors, is not trivially reproducible by script kiddies.
Why not lower?
Downgrading below CRITICAL would require evidence that container hosts represent <10% of the affected installed base — they do not; containers are the dominant Linux server deployment model in 2026. The KEV listing with confirmed exploitation in container escape campaigns eliminates any argument that the attack chain is theoretical. The user-namespace path to CAP_NET_ADMIN removes the most significant prerequisite friction on default distro configurations. The Linux kernel IS the security boundary being broken; this is not a bug in application-layer software where the blast radius is contained.
Crowdsourced verification payload.
Run this script on each target Linux host (not remotely) as any user with read access to /proc/version_info or uname. No root required. Example: chmod +x check_cve_2026_53266.sh && ./check_cve_2026_53266.sh. It checks the running kernel version against known-fixed versions and whether the ebt_snat module is loaded or loadable.
#!/usr/bin/env bash
# CVE-2026-53266 Checker — netfilter bridge ebt_snat ARP rewrite OOB write
# Checks running kernel version against fixed versions and module status.
# Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; NC='\033[0m'
KERNEL=$(uname -r)
echo "[*] Running kernel: $KERNEL"
# Extract major.minor.patch from kernel version string
# Handles formats like: 6.1.176-1~deb11u1, 5.14.0-687.24.1.el9_5, 6.12.94-1-default
VERSION=$(echo "$KERNEL" | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+')
if [[ -z "$VERSION" ]]; then
echo -e "${YELLOW}UNKNOWN${NC} — Could not parse kernel version from: $KERNEL"
exit 2
fi
MAJOR=$(echo "$VERSION" | cut -d. -f1)
MINOR=$(echo "$VERSION" | cut -d. -f2)
PATCH=$(echo "$VERSION" | cut -d. -f3)
echo "[*] Parsed version: $MAJOR.$MINOR.$PATCH"
# Version comparison function
ver_gte() {
# Returns 0 if $MAJOR.$MINOR.$PATCH >= $1.$2.$3
local cmp_maj=$1 cmp_min=$2 cmp_pat=$3
if (( MAJOR > cmp_maj )); then return 0; fi
if (( MAJOR == cmp_maj && MINOR > cmp_min )); then return 0; fi
if (( MAJOR == cmp_maj && MINOR == cmp_min && PATCH >= cmp_pat )); then return 0; fi
return 1
}
PATCHED=false
# Check against fixed versions per stable branch
if (( MAJOR >= 8 )); then
PATCHED=true
elif (( MAJOR == 7 )); then
if (( MINOR >= 1 )); then
PATCHED=true
elif (( MINOR == 0 && PATCH >= 13 )); then
PATCHED=true
fi
elif (( MAJOR == 6 )); then
if (( MINOR == 18 )) && ver_gte 6 18 36; then PATCHED=true;
elif (( MINOR == 12 )) && ver_gte 6 12 94; then PATCHED=true;
elif (( MINOR == 6 )) && ver_gte 6 6 143; then PATCHED=true;
elif (( MINOR == 1 )) && ver_gte 6 1 176; then PATCHED=true;
elif (( MINOR > 18 )); then PATCHED=true;
fi
elif (( MAJOR == 5 )); then
if (( MINOR == 15 )) && ver_gte 5 15 210; then PATCHED=true;
elif (( MINOR == 10 )) && ver_gte 5 10 259; then PATCHED=true;
fi
fi
# Check ebt_snat module status
MOD_STATUS="unknown"
if lsmod 2>/dev/null | grep -q ebt_snat; then
MOD_STATUS="loaded"
elif modprobe --dry-run ebt_snat 2>/dev/null; then
MOD_STATUS="available (not loaded)"
else
MOD_STATUS="not available (blacklisted or absent)"
fi
echo "[*] ebt_snat module: $MOD_STATUS"
# Check unprivileged user namespace status
USERNS="unknown"
if [[ -f /proc/sys/kernel/unprivileged_userns_clone ]]; then
USERNS_VAL=$(cat /proc/sys/kernel/unprivileged_userns_clone)
if [[ "$USERNS_VAL" == "0" ]]; then USERNS="disabled"; else USERNS="enabled"; fi
elif [[ -f /proc/sys/user/max_user_namespaces ]]; then
USERNS_VAL=$(cat /proc/sys/user/max_user_namespaces)
if [[ "$USERNS_VAL" == "0" ]]; then USERNS="disabled"; else USERNS="enabled ($USERNS_VAL max)"; fi
fi
echo "[*] Unprivileged user namespaces: $USERNS"
if $PATCHED; then
echo -e "\n${GREEN}PATCHED${NC} — Kernel $KERNEL contains the fix for CVE-2026-53266."
exit 0
else
echo -e "\n${RED}VULNERABLE${NC} — Kernel $KERNEL is affected by CVE-2026-53266."
if [[ "$MOD_STATUS" == "not available (blacklisted or absent)" ]]; then
echo -e "${YELLOW}NOTE:${NC} ebt_snat module is not loadable — attack path is blocked at step 3."
fi
if [[ "$USERNS" == "disabled" ]]; then
echo -e "${YELLOW}NOTE:${NC} Unprivileged user namespaces are disabled — attack path is blocked at step 2."
fi
echo "[!] Remediation: Update kernel to a fixed version and REBOOT."
exit 1
fi