The kernel's socket janitor throws away a cup someone is still drinking from, and the drinker wakes up as root
CVE-2026-53361 is a use-after-free race condition in the Linux kernel's AF_UNIX socket garbage collector (unix_gc()). The GC is supposed to reclaim in-flight file descriptors that form unreachable reference cycles. A concurrent MSG_PEEK on an in-flight fd can slip past the gc_in_progress guard — because the flag is checked and set non-atomically relative to actual GC execution — take a reference the GC's census never counted, and leave a dangling sk_buff after the GC frees the underlying socket. This dangling reference is a textbook use-after-free that can be shaped into arbitrary kernel read/write. Affected stable branches include 6.12 ≤ 6.12.94, 6.1 ≤ 6.1.176, 6.6 ≤ 6.6.143, 6.18 ≤ 6.18.37, 7.0 ≤ 7.0.13, 7.1 ≤ 7.1.2, plus distro kernels (RHEL 10, Ubuntu 24.04 HWE 6.17, Debian trixie 6.12.94). Older LTS branches 5.10 and 5.15 also received backported fixes. Kernels before 5.10 and Debian bullseye (5.10 without the vulnerable code path) are not affected.
The vendor CVSS of 7.1 (HIGH) — and Red Hat's own 7.8 — both undersell this vulnerability. The CVSS vector uses S:U (Scope: Unchanged), which is technically wrong: the demonstrated attack path crosses the container-to-host boundary, which is a scope change. More importantly, a working public exploit ('BadGarbage' by sgkdev, released 2026-08-10) achieves unprivileged local-to-root escalation and container escape in under 30 seconds on targeted kernels. For any enterprise running containerized workloads — which is the majority of Linux deployments in 2026 — the real-world severity is CRITICAL, not HIGH.
5 steps from start to impact.
Obtain unprivileged local code execution
CAP_NET_UNIX is granted by default. In multi-tenant or containerized environments this prerequisite is trivially met by any workload.- Unprivileged shell or container exec on a host running a vulnerable kernel
- On hardened single-purpose appliances with no interactive login and no container runtime, attacker must chain a separate RCE first
Trigger AF_UNIX GC race with MSG_PEEK
unix_schedule_gc() while simultaneously issuing MSG_PEEK on an in-flight fd from another thread. Because gc_in_progress is set outside unix_gc() and can read false mid-run, the peek slips through the guard and takes a reference the GC never counted. The BadGarbage PoC automates this, targeting 2–7 CPU systems for optimal race timing.- Vulnerable kernel version
- System with 2–7 CPUs (covers most VMs and containers)
- Systems with 8+ CPUs reduce race window reliability, though the PoC author notes dedicated caches remain exploitable
- Cache-armoring was stripped from public PoC, so occasional collisions with spurious allocations can occur
AF_UNIX MSG_PEEK with SCM_RIGHTS fd-passing may detect the spray pattern. No mainstream EDR signature as of 2026-09-03.Use-after-free to arbitrary kernel read/write
sk_buff. By controlling subsequent slab allocations (heap spray), they overwrite the freed object with attacker-controlled data, achieving arbitrary kernel memory read and write. The BadGarbage PoC uses a SID-leak phase to defeat KASLR before pivoting to a controlled write.- Successful race win from step 2
- KASLR adds a probabilistic step; SID-leak phase can collide with spurious allocations
/proc/sys/kernel/dmesg_restrict violations or perf anomaly detection, but this is not standard monitoring.Escalate to root and/or escape container
struct cred) to gain uid=0. In containerized environments, the exploit additionally modifies namespace pointers to break out of the container's mount, PID, and network namespaces, landing as root on the host. CloudLinux's lab testing confirmed escape from a default Docker container in under 30 seconds.- Arbitrary kernel write achieved
- Heavily customized grsecurity/PaX kernels with RANDSTRUCT may break the PoC's struct offsets, but these are rare in mainstream enterprise
auditd) for unexpected uid changes from non-root processes. Container escape may trigger Falco container.privileged alerts if namespace transitions are monitored.Lateral movement from compromised node
- Host root achieved on a node participating in a cluster or hosting sensitive workloads
- Well-segmented clusters with pod security admission and network policies limit blast radius from a single node
The supporting signals.
| In-the-wild exploitation | No confirmed in-the-wild campaigns as of 2026-09-03. Not on CISA KEV. However, public PoC released 2026-08-10 makes exploitation imminent. |
|---|---|
| Proof-of-concept | BadGarbage by sgkdev — working local root + container escape exploit. Released 2026-08-10. Targets 2–7 CPU systems on kernel 6.12 ≤ 6.12.94, Ubuntu 24.04 HWE, RHEL 10, Debian trixie. |
| EPSS score | 0.00193 (low, ~bottom 20th percentile) — likely not yet updated to reflect the public PoC released 2026-08-10. |
| KEV status | Not listed as of 2026-09-03. Given the public PoC and container-escape capability, KEV addition is plausible in the near term. |
| CVSS vector | Vendor: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H (7.1). Red Hat: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (7.8). noisgate notes S:U is incorrect — container escape is a scope change. |
| Affected versions | Kernels 5.10 ≤ 5.10.259, 5.15 ≤ 5.15.210, 6.1 ≤ 6.1.176, 6.6 ≤ 6.6.143, 6.12 ≤ 6.12.94, 6.18 ≤ 6.18.37, 7.0 ≤ 7.0.13, 7.1 ≤ 7.1.2. Distros: RHEL 10, Ubuntu 24.04 HWE, Debian trixie/bookworm. Debian bullseye not affected. |
| Fixed versions | 5.10.260, 5.15.211, 6.1.177, 6.6.144, 6.12.95, 6.18.38, 7.0.14, 7.1.3, mainline 7.2-rc1. Debian trixie: 6.12.95-1 (DSA-6381-1). Debian forky: 7.1.8-2. |
| Scanning/exposure | Local-only attack vector — not scannable via Shodan/Censys. Exposure is every Linux host running a vulnerable kernel version with local users or container workloads. Estimate: tens of millions of hosts globally. |
| Disclosure date | 2026-07-04 (NVD publication). CVSS added 2026-07-18. Public PoC released 2026-08-10. |
| Researcher | Kernel fix by upstream maintainers. Exploit PoC by sgkdev (GitHub). CloudLinux published independent lab validation of container escape. |
noisgate verdict.
The single most decisive factor is role multiplier — the affected component is the Linux kernel itself, and the demonstrated container-escape chain ends in host root on every Kubernetes node, Docker host, and multi-tenant server running a vulnerable version. A public, working exploit achieves this from any unprivileged container in under 30 seconds, making the vendor's HIGH (7.1) rating an undercount of real-world blast radius.
Why this verdict
- Public weaponized exploit: BadGarbage (sgkdev, 2026-08-10) achieves unprivileged container escape to host root in <30 seconds on targeted kernels. This eliminates any theoretical-only discount.
- Role multiplier: The affected component is the Linux kernel. In containerized deployments (Kubernetes nodes, Docker hosts, CI runners), the kernel IS the trust boundary. Container escape = node root = kubelet credential theft = potential cluster-wide compromise. ≥50% of enterprise Linux hosts run container workloads in 2026, placing the majority of the installed base in a high-value role. Blast radius is fleet-scale — one compromised pod per node is sufficient.
- Minimal friction for realistic attacker: Requires only unprivileged local access (PR:L). In any environment accepting untrusted container workloads — multi-tenant Kubernetes, CI/CD, managed PaaS — this prerequisite is the *default starting position* for an attacker, not a barrier. The race condition is reliable on 2–7 CPU systems, which covers the vast majority of production VMs and containers.
- Scope undercount in vendor CVSS: Both the NVD vector (7.1) and Red Hat vector (7.8) use
S:U. The demonstrated container-to-host escape is textbookS:C, which alone would raise the Red Hat score to 8.8. Combined with the public PoC, CRITICAL is warranted. - Broad affected surface: Every major enterprise distro shipping kernel 6.1–7.1 is affected: RHEL 10, Ubuntu 24.04 HWE, Debian bookworm/trixie, plus cloud-optimized kernels. The fix has been available since May 2026, but kernel patching cadence in large fleets means many hosts remain unpatched.
Why not higher?
A 9.0 is already near the top of the CRITICAL band. A 10.0 would require unauthenticated remote exploitation or wormable characteristics. This vulnerability requires local access (though containers trivially satisfy that). The PoC is less reliable on 8+ CPU systems, providing a marginal friction point that prevents a 9.5+ score.
Why not lower?
Downgrading below CRITICAL is blocked by the role-multiplier floor: the Linux kernel is the canonical high-value-role component (it is the container trust boundary itself), the public PoC demonstrates fleet-scale blast radius via container escape, and ≥50% of enterprise Linux deployments run container workloads. The 'local access required' friction is nullified by the container threat model where local access is the attacker's starting position.
What to do — in priority order.
- Disable AF_UNIX GC via sysctl if feasible — Set
net.unix.max_dgram_qlento 0 or restrictSCM_RIGHTSfd-passing via seccomp on container workloads. This breaks the exploit's prerequisite. However, disabling SCM_RIGHTS may break applications that pass file descriptors (e.g., container runtimes, systemd socket activation). Test thoroughly. Deploy within 3 days per noisgate mitigation SLA for CRITICAL. - Apply restrictive seccomp profiles blocking MSG_PEEK on AF_UNIX sockets — A custom seccomp profile that blocks
recvmsgwithMSG_PEEKflag onAF_UNIXsockets eliminates the race trigger. KubernetesRuntimeDefaultseccomp does NOT block this — you need a custom profile. Deploy within 3 days. - Pin container workloads to 8+ CPU cgroups — The public PoC is optimized for 2–7 CPUs and is less reliable on 8+ CPU systems. Pinning containers to larger CPU sets raises the exploitation bar. This is a speed bump, not a fix. Deploy within 3 days as an interim measure alongside patching.
- Enable Falco or runtime detection for AF_UNIX fd-passing anomalies — Deploy Falco rules that alert on high-volume
SCM_RIGHTSfd-passing combined withMSG_PEEKon Unix sockets. This detects the spray phase of the exploit. Deploy within 3 days.
- Kubernetes Pod Security Standards (restricted profile) — the restricted profile blocks privileged containers and host namespaces but does NOT prevent the kernel-level race condition. The exploit works from an unprivileged pod with default seccomp.
- AppArmor default Docker profile — does not restrict
AF_UNIXsocket operations orMSG_PEEK. The exploit operates entirely within allowed syscalls. - Network segmentation / firewalls — irrelevant; the attack is local and uses Unix domain sockets, not network sockets.
- Read-only root filesystem — does not affect the exploit, which operates entirely in memory via kernel socket structures.
Crowdsourced verification payload.
Run this script on each target Linux host (or via your fleet management tool like Ansible/Salt) as any user. Example: bash check_cve_2026_53361.sh. No root privileges required — it only checks the running kernel version.
#!/bin/bash\n# check_cve_2026_53361.sh\n# Checks if the running kernel is vulnerable to CVE-2026-53361\n# (AF_UNIX GC race condition / BadGarbage)\n# Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN\n\nKERNEL=$(uname -r)\nVERSION=$(echo \"$KERNEL\" | grep -oP '^[0-9]+\\.[0-9]+\\.[0-9]+')\nMAJOR=$(echo \"$VERSION\" | cut -d. -f1)\nMINOR=$(echo \"$VERSION\" | cut -d. -f2)\nPATCH=$(echo \"$VERSION\" | cut -d. -f3)\n\nif [ -z \"$MAJOR\" ] || [ -z \"$MINOR\" ] || [ -z \"$PATCH\" ]; then\n echo \"UNKNOWN - Could not parse kernel version: $KERNEL\"\n exit 2\nfi\n\nvulnerable=0\n\n# Check each affected branch\nif [ \"$MAJOR\" -eq 5 ] && [ \"$MINOR\" -eq 10 ] && [ \"$PATCH\" -le 259 ]; then\n vulnerable=1\nelif [ \"$MAJOR\" -eq 5 ] && [ \"$MINOR\" -eq 15 ] && [ \"$PATCH\" -le 210 ]; then\n vulnerable=1\nelif [ \"$MAJOR\" -eq 6 ] && [ \"$MINOR\" -eq 1 ] && [ \"$PATCH\" -le 176 ]; then\n vulnerable=1\nelif [ \"$MAJOR\" -eq 6 ] && [ \"$MINOR\" -eq 6 ] && [ \"$PATCH\" -le 143 ]; then\n vulnerable=1\nelif [ \"$MAJOR\" -eq 6 ] && [ \"$MINOR\" -eq 12 ] && [ \"$PATCH\" -le 94 ]; then\n vulnerable=1\nelif [ \"$MAJOR\" -eq 6 ] && [ \"$MINOR\" -eq 18 ] && [ \"$PATCH\" -le 37 ]; then\n vulnerable=1\nelif [ \"$MAJOR\" -eq 7 ] && [ \"$MINOR\" -eq 0 ] && [ \"$PATCH\" -le 13 ]; then\n vulnerable=1\nelif [ \"$MAJOR\" -eq 7 ] && [ \"$MINOR\" -eq 1 ] && [ \"$PATCH\" -le 2 ]; then\n vulnerable=1\nfi\n\nif [ \"$vulnerable\" -eq 1 ]; then\n echo \"VULNERABLE - Kernel $KERNEL is affected by CVE-2026-53361\"\n exit 1\nelse\n echo \"PATCHED - Kernel $KERNEL is not in a known vulnerable range\"\n exit 0\nfiIf you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.