← Back to Feed CACHED · 2026-09-26 06:57:13 · CACHE_KEY CVE-2026-76654
CVE-2026-76654 · CWE-59 · Disclosed 2026-09-23

Kubernetes kubelet subPath symlink resolution permits NTLM credential coercion on Windows nodes

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

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.

"Kubelet on Windows follows symlinks to UNC paths, leaking its NTLM hash to any pod author."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Obtain Pod-Creation Privileges

The attacker needs a valid kubeconfig or compromised ServiceAccount token granting 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.
Conditions required:
  • Valid credentials with create pods RBAC
  • Target namespace permits scheduling on Windows nodes
Where this breaks in practice:
  • Requires prior cluster access — unauthenticated attackers cannot reach this step
  • PodSecurity admission or OPA/Gatekeeper policies may block subPath usage or restrict node selectors
Detection/coverage: Kubernetes audit logs capture pod creation events (audit.k8s.io/v1 — verb create, resource pods). RBAC alerts on unusual service accounts creating pods on Windows node pools.
STEP 02

Craft Malicious Pod Spec with UNC Symlink subPath

The attacker authors a Pod manifest with a 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.
Conditions required:
  • Ability to write a symlink into a volume source on the target Windows node
  • Volume type that permits symlink creation (emptyDir, hostPath, PVC)
Where this breaks in practice:
  • Some hardened Windows images disable symlink creation for non-admin users
  • Admission webhooks that inspect volumeMount subPath values can intercept UNC patterns
Detection/coverage: Admission controller logs; Falco or similar runtime rules that flag symlink creation pointing to UNC paths inside container volumes.
STEP 03

Kubelet Resolves Symlink and Initiates SMB Session

When the kubelet on the Windows node processes the pod's volume mount, it calls 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.
Conditions required:
  • Kubelet running a vulnerable version on a Windows node
  • Outbound TCP 445 from the Windows node to the attacker's listener is not blocked
Where this breaks in practice:
  • 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
Detection/coverage: Windows Security Event IDs 4648 (logon with explicit credentials) and 4624 type 3 (network logon). Network monitoring for outbound SMB to non-standard destinations. GreyNoise/NGFW anomaly detection on port 445.
STEP 04

Capture NetNTLMv2 Hash

The attacker runs a tool such as Responder or ntlmrelayx (from Impacket) on their listener host. When the kubelet's SMB session arrives, the tool captures the NetNTLMv2 challenge-response. This hash represents the identity under which the kubelet Windows service runs — typically the computer account (e.g., NODE01$) or a domain service account if explicitly configured.
Conditions required:
  • Attacker has a listener accepting SMB on the receiving end
  • Network path from the Windows node to the listener exists
Where this breaks in practice:
  • 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)
Detection/coverage: NTLM authentication telemetry in Windows Event Forwarding. Network IDS signatures for Responder/ntlmrelayx protocol anomalies.
STEP 05

Relay Hash to Domain Target

Rather than cracking the hash (impractical for machine accounts), the attacker relays it in real-time to a domain service that accepts NTLM without Extended Protection for Authentication (EPA). Prime targets include ADCS HTTP enrollment (/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.
Conditions required:
  • Target service accepts NTLM without EPA or signing enforcement
  • ADCS web enrollment or LDAP endpoint reachable from the relay position
Where this breaks in practice:
  • 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
Detection/coverage: ADCS certificate issuance logs (Event ID 4887). LDAP signing failure events. EDR behavioral rules for ntlmrelayx/Certipy execution.
03 · Compensating Control

1
HIGH 7.0→LOW 3.0
SEVERITY REDUCED
Block outbound SMB (TCP 445) from Kubernetes Windows node subnets — Create firewall rules (host-based Windows Firewall via GPO and network-layer ACLs) that deny TCP 445 outbound from all K8s Windows node VLANs to any destination except authorized file servers. This breaks the core exploitation mechanism — the kubelet cannot reach the attacker's SMB listener. Deploy within 30 days per the noisgate mitigation SLA for HIGH.
2
HIGH 7.0→MEDIUM 5.0
SEVERITY REDUCED
Enforce EPA on ADCS web enrollment endpoints — Apply KB5005413 and configure IIS on all ADCS servers to require Extended Protection for Authentication (EPA). This blocks NTLM relay to certificate enrollment — the highest-value relay target — even if the hash is captured. Configure via Set-WebConfigurationProperty on the /certsrv application. Deploy within 30 days.
3
HIGH 7.0→MEDIUM 4.5
SEVERITY REDUCED
Enforce LDAP signing and channel binding on all DCs — Set 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.
4
HIGH 7.0→MEDIUM 5.5
SEVERITY REDUCED
Restrict pod-creation RBAC to break the prerequisite — Audit and tighten 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.
5
HIGH 7.0→IGNORE 0.0
SEVERITY REDUCED
Upgrade kubelet to patched versions — Apply the vendor fix: kubelet ≥ v1.34.12, ≥ v1.35.9, ≥ v1.36.5, or ≥ v1.37.1. The fix rejects any subPath symlink target beginning with \\, 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.
What doesn't work
  • 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 restricted profile — 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.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNone 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-ConceptNo 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 ScoreNot 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 StatusNot listed as of 2026-09-26.
CVSS VectorCVSS: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 Versionskubelet ≤ 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 Versionskubelet ≥ 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 & ExposureShodan 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 & CreditsDisclosed 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 VulnerabilitiesConceptually 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.

  1. Kubernetes Security Advisory (discuss.kubernetes.io)
  2. Kubernetes Fix PR — Refuse UNC symlink targets (release-1.36)
  3. AWS EKS Distro Tracking Issue
  4. Vulners — CVE-2026-76654
  5. SpecterOps — NTLM Relay Renaissance (Relay Chain Reference)
  6. Horizon3 — NTLM Coercion Impact & Risk
  7. Kubernetes Issue #142098 — CVE Placeholder
  8. Flatcar Security Triage — 2026-09-24
05 · The Call

Final Verdict
↑ UPGRADED to HIGH (7.0/10)

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 → Certipy auth → 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.

06 · Verification

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

noisgate-verify.ps1
POWERSHELLREAD-ONLYSAFE
#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
}
Peer Review

What defenders are saying.

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