Your Kubernetes worker just handed its domain password to anyone who can schedule a pod
CVE-2026-76654 affects the kubelet component on Windows-only Kubernetes nodes across all supported release branches: v1.34.x through v1.34.11, v1.35.x through v1.35.8, v1.36.x through v1.36.4, and v1.37.0. When a pod's volumeMount specifies a subPath that is a symbolic link, the kubelet's subpath resolver on Windows only blocked \\?\ and \\.\ device-style paths — it happily followed ordinary UNC paths like \\attacker\share. Following that path triggers an automatic SMB session, sending the kubelet service account's NetNTLMv2 hash to the attacker's listener. This is a textbook forced-authentication primitive (MITRE ATT&CK T1187).
The Kubernetes Product Security Committee assigned this a CVSS 5.8 MEDIUM (CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:N/A:N). That score correctly captures the high-privilege prerequisite and the indirect confidentiality impact, but it underweights the blast radius in enterprise environments where Windows K8s nodes are domain-joined. In those deployments — which represent a meaningful share of the Windows-on-K8s installed base — the captured NetNTLMv2 hash can be relayed to ADCS web enrollment or unsigned LDAP to achieve machine-certificate issuance or AD object manipulation. The Kubernetes advisory itself acknowledges the Changed scope (S:C), signaling impact beyond the vulnerable component. noisgate upgrades this to HIGH because Kubernetes is a canonically high-value orchestration component and the NTLM coercion-to-relay chain is a well-documented path to domain-level compromise.
5 steps from start to impact.
Obtain Pod-Creation Privileges
create pods RBAC in a namespace that can schedule workloads onto Windows nodes (via nodeSelector or nodeAffinity). In multi-tenant clusters, CI/CD service accounts or developer namespaces commonly hold this privilege. No API server exploit is required — the attacker operates through legitimate Kubernetes API calls.- Valid credentials with
create podsRBAC - Target namespace permits scheduling on Windows nodes
- Requires prior cluster access — unauthenticated attackers cannot reach this step
- PodSecurity admission or OPA/Gatekeeper policies may block subPath usage or restrict node selectors
audit.k8s.io/v1 — verb create, resource pods). RBAC alerts on unusual service accounts creating pods on Windows node pools.Craft Malicious Pod Spec with UNC Symlink subPath
volumeMount whose subPath resolves to a symbolic link pointing at a UNC path such as \\attacker.evil\share. The symlink can be planted in a writable volume (emptyDir, hostPath, or PVC) via an init container or a prior container execution. The pod spec itself is a normal YAML — no exploit payload, no shellcode.- Ability to write a symlink into a volume source on the target Windows node
- Volume type that permits symlink creation (emptyDir, hostPath, PVC)
- Some hardened Windows images disable symlink creation for non-admin users
- Admission webhooks that inspect volumeMount subPath values can intercept UNC patterns
Kubelet Resolves Symlink and Initiates SMB Session
EvalSymlinks() on the subPath. The vulnerable code path only rejects \\?\ and \\.\ device prefixes — ordinary UNC paths like \\attacker\share pass through. The kubelet follows the symlink, which causes the Windows networking stack to open an outbound SMB connection (TCP 445) to the attacker-specified host. The machine's NTLM credentials are sent automatically as part of SMB authentication.- Kubelet running a vulnerable version on a Windows node
- Outbound TCP 445 from the Windows node to the attacker's listener is not blocked
- Enterprise perimeter firewalls typically block outbound SMB (TCP 445) to the internet
- Internal network segmentation may restrict SMB from the Kubernetes node VLAN
- Next-gen firewalls and EDR may alert on anomalous outbound SMB
Capture NetNTLMv2 Hash
NODE01$) or a domain service account if explicitly configured.- Attacker has a listener accepting SMB on the receiving end
- Network path from the Windows node to the listener exists
- If the kubelet runs as LocalSystem (non-domain-joined node), the hash has no domain value
- NetNTLMv2 hashes resist offline brute-force if the underlying password is strong (computer accounts use 120-char random passwords by default)
Relay Hash to Domain Target
/certsrv), LDAP without channel binding, and WMI/DCOM endpoints without signing. A successful relay to ADCS yields a machine certificate the attacker can use for Kerberos PKINIT authentication as the node's computer account. Tools: ntlmrelayx with --adcs flag, Certipy for post-relay certificate abuse.- Target service accepts NTLM without EPA or signing enforcement
- ADCS web enrollment or LDAP endpoint reachable from the relay position
- Modern AD configurations with LDAP signing and channel binding block relay
- ADCS enrollment hardened with EPA (KB5005413+) blocks relay to certsrv
- SMB signing enforced by default on DCs since Server 2025 prevents SMB relay
Set-WebConfigurationProperty on the /certsrv application. Deploy within 30 days.LdapEnforceChannelBinding=2 and ldapserverintegrity=2 via GPO on all domain controllers. This eliminates LDAP as an NTLM relay target. Combined with ADCS EPA, this removes the two most impactful relay destinations. Deploy within 30 days.create pods ClusterRoleBindings and RoleBindings. Ensure only CI/CD service accounts and cluster-admin roles can schedule pods on Windows node pools. Use nodeSelector restrictions and PodSecurity admission to prevent non-privileged namespaces from targeting Windows nodes. This shrinks the attacker surface from 'anyone with pod create' to 'hardened automation accounts only.' Deploy within 30 days.\\, eliminating the UNC resolution entirely. This is the definitive remediation. Deploy within 180 days per the noisgate remediation SLA for HIGH, but prioritize within 30 days if Windows nodes are domain-joined.- Kubernetes NetworkPolicies — these control pod-to-pod traffic at the CNI level. The NTLM coercion occurs at the *kubelet* process level on the host OS, completely outside the CNI data plane. NetworkPolicies do not affect host-level SMB sessions.
- Linux-based hardening (AppArmor, SELinux, seccomp) — this vulnerability is Windows-only. Linux security modules have no effect on Windows kubelet behavior.
- Disabling NTLMv1 (LmCompatibilityLevel=5) — this forces NTLMv2 but does NOT prevent NTLMv2 hash capture or relay. The captured NetNTLMv2 hash is fully relayable regardless of LmCompatibilityLevel setting.
- Pod Security Standards
restrictedprofile — the restricted profile blocks hostPath and privileged containers but does NOT restrict subPath symlink content. A pod can still use an emptyDir volume with a symlink subPath under the restricted profile.
The supporting signals.
| In-the-Wild Exploitation | None observed. Not listed on CISA KEV. No reports from threat intelligence vendors or OSINT feeds. Disclosed 3 days ago (2026-09-23); the attack window is early. |
|---|---|
| Proof-of-Concept | No public PoC repository found. However, exploitation is conceptually trivial — a two-file pod manifest (init container plants symlink, main container triggers subPath resolution) combined with Responder or ntlmrelayx on the listener side. No novel tooling required; all components are stock red-team utilities. |
| EPSS Score | Not yet scored — CVE was disclosed 2026-09-23, too recent for FIRST EPSS model ingestion. Expect a low initial score (<0.05) given the high-privilege prerequisite and Windows-node niche. |
| KEV Status | Not listed as of 2026-09-26. |
| CVSS Vector | CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:N/A:N — 5.8 Medium per Kubernetes Product Security Committee. Changed Scope (S:C) reflects that the leaked credential impacts systems beyond kubelet itself. The PR:H acknowledges that pod creation is a privileged operation. |
| Affected Versions | kubelet ≤ v1.34.11, ≤ v1.35.8, ≤ v1.36.4, and v1.37.0 — Windows nodes only. Linux and macOS nodes are not affected. The flaw was introduced when the subPath symlink resolver was first implemented for Windows. |
| Fixed Versions | kubelet ≥ v1.34.12, ≥ v1.35.9, ≥ v1.36.5, ≥ v1.37.1. Fix treats any path beginning with \\ as a device/UNC path that is never followed. Backports merged 2026-09-23 across all four supported branches. |
| Scanning & Exposure | Shodan indexes ~1M Kubernetes-related services; however, kubelet ports (10250/10255) should not be internet-exposed, and this CVE requires authenticated pod creation, not external kubelet access. The real exposure surface is internal: any AD-joined Windows K8s node pool. No GreyNoise or Censys tags specific to this CVE yet. |
| Disclosure & Credits | Disclosed 2026-09-23 by the Kubernetes Third-Party Security Audit subproject, conducted by OSTIF and Shielder. Fixes authored by Yuanliang Zhang, Verónica López, Jeremy Rickard, and Nathan Herz. |
| Related Vulnerabilities | Conceptually related to CVE-2021-25741 (symlink exchange for host filesystem access via subPath) — same code area (pkg/volume/util/subpath/), same attack surface, different impact class. The NTLM coercion pattern mirrors PetitPotam (CVE-2021-36942) and PrinterBug/SpoolSample techniques. |
Sources.
- Kubernetes Security Advisory (discuss.kubernetes.io)
- Kubernetes Fix PR — Refuse UNC symlink targets (release-1.36)
- AWS EKS Distro Tracking Issue
- Vulners — CVE-2026-76654
- SpecterOps — NTLM Relay Renaissance (Relay Chain Reference)
- Horizon3 — NTLM Coercion Impact & Risk
- Kubernetes Issue #142098 — CVE Placeholder
- Flatcar Security Triage — 2026-09-24
Why this verdict
- PR:H narrows the attacker pool but does not eliminate it. Pod creation RBAC is routinely granted to CI/CD pipelines, developer service accounts, and GitOps controllers. In clusters with >50 namespaces, the practical attacker surface is wider than 'high privilege' implies. This friction justifies staying at the low end of HIGH rather than mid-HIGH, but it does not push below the floor.
- Windows-only scope limits the affected population to ~8-12% of Kubernetes clusters per industry estimates (CNCF surveys do not publish Windows-node breakdowns, but SIG-Windows community sizing and managed-service documentation suggest single-digit-to-low-double-digit percentages). This is above the 1% threshold required to maintain the high-value-role floor.
- NTLM relay chain to domain takeover is a documented, repeatable path. The captured kubelet hash (typically a computer account) can be relayed to ADCS web enrollment to obtain a machine certificate, then used for PKINIT-based Kerberos authentication. This chain — ntlmrelayx
--adcs→ Certipyauth→ secretsdump — has been demonstrated against real AD environments by SpecterOps, Horizon3, and others. It works unless EPA is enforced on the ADCS endpoint (KB5005413). - Role multiplier: Kubernetes orchestration nodes. (a) *Low-value role:* Dev/test K8s clusters with Windows nodes not domain-joined — hash has no relay value, impact is LOCAL, severity stays MEDIUM. (b) *Typical role:* Production K8s cluster with domain-joined Windows nodes running .NET workloads — hash relay to domain services is feasible, blast radius is HOST → potentially DOMAIN. (c) *High-value role:* Enterprise K8s clusters where Windows nodes host line-of-business containers and the kubelet service account is a domain computer account with default AD permissions — relay to ADCS yields machine cert, enabling PKINIT auth as the node, lateral movement to other domain resources, and potential escalation to DA via RBAC abuse or Kerberos delegation. Blast radius: domain-scale. This role represents ≥1% of the affected installed base (Windows K8s nodes are overwhelmingly in enterprise/AD environments), triggering the HIGH floor.
- Outbound SMB filtering is the single strongest friction point. Enterprises blocking TCP 445 outbound from K8s node VLANs eliminate the external-attacker relay path entirely. However, an attacker with *any* internal foothold (e.g., a compromised pod on the same network) can host Responder internally, bypassing perimeter controls. This internal-relay scenario is realistic in the Windows-K8s deployment profile.
Why not higher?
A CRITICAL rating would require either unauthenticated remote exploitation or a guaranteed domain-takeover chain. This CVE requires PR:H (pod creation privileges), meaning the attacker is already authenticated to the cluster. The hash capture alone is not RCE — it is a credential-exposure primitive that requires a second-stage relay. Modern AD hardening (LDAP channel binding, EPA on ADCS, SMB signing on DCs) breaks the relay chain entirely. The Windows-node population is a minority of the K8s installed base, further limiting blast radius below CRITICAL thresholds.
Why not lower?
Despite the high-privilege prerequisite, Kubernetes is a canonically high-value orchestration component and the NTLM coercion-to-relay attack chain is not theoretical — it is a stock red-team technique with mature tooling (ntlmrelayx, Certipy, Responder). Domain-joined Windows K8s nodes are the norm in enterprise deployments, meaning the relay-to-ADCS path is live in a substantial fraction of affected environments. Dropping to MEDIUM would ignore the Changed Scope (S:C) and the domain-scale blast radius that relay enables.
Crowdsourced verification payload.
Run this script on each Windows Kubernetes node (or remotely via Invoke-Command -ComputerName <node>). Requires read access to the kubelet binary. Example: powershell -ExecutionPolicy Bypass -File .\Check-CVE-2026-76654.ps1
#Requires -Version 5.1
<#
.SYNOPSIS
Checks whether the local Windows kubelet is vulnerable to CVE-2026-76654
(NTLM coercion via UNC subPath symlink resolution).
.NOTES
Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
#>
$ErrorActionPreference = 'Stop'
# Gate: Windows only
if ($env:OS -ne 'Windows_NT') {
Write-Host 'UNKNOWN - This check applies only to Windows Kubernetes nodes.'
exit 2
}
# Locate kubelet binary
$kubeletExe = $null
$searchPaths = @(
(Get-Command kubelet -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source),
'C:\k\kubelet.exe',
'C:\usr\bin\kubelet.exe',
"$env:ProgramFiles\containerd\kubelet.exe",
"$env:ProgramFiles\kubernetes\kubelet.exe"
) | Where-Object { $_ }
foreach ($p in $searchPaths) {
if (Test-Path $p) { $kubeletExe = $p; break }
}
if (-not $kubeletExe) {
Write-Host 'UNKNOWN - kubelet binary not found on this host.'
exit 2
}
# Get version
try {
$raw = & $kubeletExe --version 2>&1 | Out-String
} catch {
Write-Host "UNKNOWN - Failed to execute kubelet: $_"
exit 2
}
if ($raw -notmatch 'v(\d+)\.(\d+)\.(\d+)') {
Write-Host "UNKNOWN - Could not parse version from: $raw"
exit 2
}
$maj = [int]$Matches[1]; $min = [int]$Matches[2]; $pat = [int]$Matches[3]
Write-Host "Detected kubelet version: v$maj.$min.$pat"
# Fixed versions: v1.34.12, v1.35.9, v1.36.5, v1.37.1
$vuln = $false
switch ($min) {
{ $_ -lt 34 } { $vuln = $true } # unsupported, likely vulnerable
34 { if ($pat -le 11) { $vuln = $true } }
35 { if ($pat -le 8) { $vuln = $true } }
36 { if ($pat -le 4) { $vuln = $true } }
37 { if ($pat -eq 0) { $vuln = $true } }
default { $vuln = $false } # v1.38+ should include fix
}
if ($vuln) {
Write-Host "VULNERABLE - kubelet v$maj.$min.$pat is affected by CVE-2026-76654."
Write-Host "Upgrade to the next patch release in the v1.$min.x branch."
exit 1
} else {
Write-Host "PATCHED - kubelet v$maj.$min.$pat includes the fix for CVE-2026-76654."
exit 0
}