Kubernetes - Windows nodes - Insufficient input sanitization leads to privilege escalation
Description
A security issue was discovered in Kubernetes where a user that can create pods on Windows nodes may be able to escalate to admin privileges on those nodes. Kubernetes clusters are only affected if they include Windows nodes.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Kubernetes users with pod creation ability on Windows nodes can escalate to admin due to insufficient input sanitization.
Vulnerability
Details
A security issue in Kubernetes (CVE-2023-3676) allows a user who can create pods on Windows nodes to escalate privileges to admin on those nodes. The root cause is insufficient input sanitization in kubelet when handling paths and subpaths for volume mounts on Windows [2]. Specifically, the subpath could be passed as a PowerShell subexpression, which would then be executed by kubelet with elevated privileges [2].
Exploitation and
Impact
Exploitation requires the ability to create pods on Windows nodes; no additional authentication is needed. The attack vector is network-based (AV:N) with low complexity (AC:L) and low privileges (PR:L) [3]. A successful exploit grants an attacker full administrative control over the Windows node, leading to complete compromise of confidentiality, integrity, and availability [1][3]. Kubernetes clusters without Windows nodes are not affected [1].
Mitigation
The vulnerability affects kubelet versions up to v1.28.0, v1.27.4, v1.26.7, v1.25.12, and v1.24.16. Patches are available in kubelet v1.28.1, v1.27.5, v1.26.8, v1.25.13, and v1.24.17 [3]. The fix uses environment variables to pass paths and subpaths to PowerShell, preventing subexpression evaluation [2]. No other mitigations are known, and full mitigation requires applying patches for related CVEs CVE-2023-3955 and CVE-2023-3893 [3]. Detection via audit logs is possible by monitoring pod create events for embedded PowerShell commands [3].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
k8s.io/kubernetesGo | >= 1.28.0, < 1.28.1 | 1.28.1 |
k8s.io/kubernetesGo | >= 1.27.0, < 1.27.5 | 1.27.5 |
k8s.io/kubernetesGo | >= 1.26.0, < 1.26.8 | 1.26.8 |
k8s.io/kubernetesGo | >= 1.25.0, < 1.25.13 | 1.25.13 |
k8s.io/kubernetesGo | < 1.24.17 | 1.24.17 |
Affected products
66- osv-coords65 versionspkg:apk/chainguard/aws-ebs-csi-driver-1.18pkg:apk/chainguard/aws-efs-csi-driver-fipspkg:apk/chainguard/aws-efs-csi-driver-fips-1.6pkg:apk/chainguard/calico-cni-fips-3.25-compatpkg:apk/chainguard/calico-cni-fips-compatpkg:apk/chainguard/calicoctl-fipspkg:apk/chainguard/calicoctl-fips-3.25pkg:apk/chainguard/calico-fipspkg:apk/chainguard/calico-fips-3.25pkg:apk/chainguard/calico-fips-apiserverpkg:apk/chainguard/calico-fips-apiserver-3.25pkg:apk/chainguard/calico-fips-app-policypkg:apk/chainguard/calico-fips-app-policy-3.25pkg:apk/chainguard/calico-fips-cnipkg:apk/chainguard/calico-fips-cni-3.25pkg:apk/chainguard/calico-fips-felixpkg:apk/chainguard/calico-fips-felix-3.25pkg:apk/chainguard/calico-fips-key-cert-provisionerpkg:apk/chainguard/calico-fips-kube-controllerspkg:apk/chainguard/calico-fips-kube-controllers-3.25pkg:apk/chainguard/calico-fips-nodepkg:apk/chainguard/calico-fips-node-3.25pkg:apk/chainguard/calico-fips-pod2daemonpkg:apk/chainguard/calico-fips-pod2daemon-3.25pkg:apk/chainguard/calico-fips-typha-clientpkg:apk/chainguard/calico-fips-typha-client-3.25pkg:apk/chainguard/calico-fips-typhadpkg:apk/chainguard/calico-fips-typhad-3.25pkg:apk/chainguard/cluster-autoscaler-fips-1.25pkg:apk/chainguard/cluster-autoscaler-fips-1.25-compatpkg:apk/chainguard/kubeflow-pipelinespkg:apk/chainguard/kubeflow-pipelines-apiserverpkg:apk/chainguard/kubeflow-pipelines-cache-deployerpkg:apk/chainguard/kubeflow-pipelines-cache-deployer-compatpkg:apk/chainguard/kubeflow-pipelines-cache_serverpkg:apk/chainguard/kubeflow-pipelines-frontendpkg:apk/chainguard/kubeflow-pipelines-metadata-envoy-configpkg:apk/chainguard/kubeflow-pipelines-metadata-writerpkg:apk/chainguard/kubeflow-pipelines-metadata-writer-compatpkg:apk/chainguard/kubeflow-pipelines-persistence_agentpkg:apk/chainguard/kubeflow-pipelines-scheduledworkflowpkg:apk/chainguard/kubeflow-pipelines-viewer-crd-controllerpkg:apk/chainguard/kubernetes-dns-node-cache-1.17pkg:apk/chainguard/nodetaintpkg:apk/chainguard/sparkctlpkg:apk/chainguard/spark-operatorpkg:apk/chainguard/spark-operator-oci-entrypointpkg:apk/wolfi/kubeflow-pipelinespkg:apk/wolfi/kubeflow-pipelines-apiserverpkg:apk/wolfi/kubeflow-pipelines-cache-deployerpkg:apk/wolfi/kubeflow-pipelines-cache-deployer-compatpkg:apk/wolfi/kubeflow-pipelines-cache_serverpkg:apk/wolfi/kubeflow-pipelines-frontendpkg:apk/wolfi/kubeflow-pipelines-metadata-envoy-configpkg:apk/wolfi/kubeflow-pipelines-metadata-writerpkg:apk/wolfi/kubeflow-pipelines-metadata-writer-compatpkg:apk/wolfi/kubeflow-pipelines-persistence_agentpkg:apk/wolfi/kubeflow-pipelines-scheduledworkflowpkg:apk/wolfi/kubeflow-pipelines-viewer-crd-controllerpkg:apk/wolfi/nodetaintpkg:apk/wolfi/sparkctlpkg:apk/wolfi/spark-operatorpkg:apk/wolfi/spark-operator-oci-entrypointpkg:golang/k8s.io/kubernetespkg:rpm/opensuse/govulncheck-vulndb&distro=openSUSE%20Tumbleweed
< 1.18.0-r15+ 64 more
- (no CPE)range: < 1.18.0-r15
- (no CPE)range: < 1.7.0-r5
- (no CPE)range: < 1.6.0-r5
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 0
- (no CPE)range: < 3.25.2-r5
- (no CPE)range: < 1.25.3-r7
- (no CPE)range: < 1.25.3-r7
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: < 0
- (no CPE)range: >= 1.28.0, < 1.28.1
- (no CPE)range: < 0.0.20241213T205935-1.1
- Kubernetes/kubeletv5Range: v1.28.0
Patches
5a53faf5e17edMerge pull request #120133 from ritazh/cherry-pick-cve-2023-3676-1.24
1 file changed · +8 −4
pkg/volume/util/subpath/subpath_windows.go+8 −4 modified@@ -76,8 +76,10 @@ func getUpperPath(path string) string { // Check whether a directory/file is a link type or not // LinkType could be SymbolicLink, Junction, or HardLink func isLinkPath(path string) (bool, error) { - cmd := fmt.Sprintf("(Get-Item -LiteralPath %q).LinkType", path) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).LinkType") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", path)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return false, err } @@ -114,8 +116,10 @@ func evalSymlink(path string) (string, error) { } } // This command will give the target path of a given symlink - cmd := fmt.Sprintf("(Get-Item -LiteralPath %q).Target", upperpath) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).Target") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", upperpath)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return "", err }
073f9ea33a93Merge pull request #120132 from ritazh/cherry-pick-cve-2023-3676-1.25
1 file changed · +9 −4
pkg/volume/util/subpath/subpath_windows.go+9 −4 modified@@ -76,8 +76,10 @@ func getUpperPath(path string) string { // Check whether a directory/file is a link type or not // LinkType could be SymbolicLink, Junction, or HardLink func isLinkPath(path string) (bool, error) { - cmd := fmt.Sprintf("(Get-Item -LiteralPath %q).LinkType", path) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).LinkType") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", path)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return false, err } @@ -114,8 +116,11 @@ func evalSymlink(path string) (string, error) { } } // This command will give the target path of a given symlink - cmd := fmt.Sprintf("(Get-Item -LiteralPath %q).Target", upperpath) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + // The -Force parameter will allow Get-Item to also evaluate hidden folders, like AppData. + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).Target") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", upperpath)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return "", err }
39cc101c7855Merge pull request #120131 from ritazh/cherry-pick-cve-2023-3676-1.26
1 file changed · +8 −4
pkg/volume/util/subpath/subpath_windows.go+8 −4 modified@@ -76,8 +76,10 @@ func getUpperPath(path string) string { // Check whether a directory/file is a link type or not // LinkType could be SymbolicLink, Junction, or HardLink func isLinkPath(path string) (bool, error) { - cmd := fmt.Sprintf("(Get-Item -LiteralPath %q).LinkType", path) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).LinkType") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", path)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return false, err } @@ -115,8 +117,10 @@ func evalSymlink(path string) (string, error) { } // This command will give the target path of a given symlink // The -Force parameter will allow Get-Item to also evaluate hidden folders, like AppData. - cmd := fmt.Sprintf("(Get-Item -Force -LiteralPath %q).Target", upperpath) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).Target") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", upperpath)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return "", err }
74b617310c24Merge pull request #120129 from ritazh/cherry-pick-cve-2023-3676-1.28
1 file changed · +8 −4
pkg/volume/util/subpath/subpath_windows.go+8 −4 modified@@ -76,8 +76,10 @@ func getUpperPath(path string) string { // Check whether a directory/file is a link type or not // LinkType could be SymbolicLink, Junction, or HardLink func isLinkPath(path string) (bool, error) { - cmd := fmt.Sprintf("(Get-Item -LiteralPath %q).LinkType", path) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).LinkType") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", path)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return false, err } @@ -115,8 +117,10 @@ func evalSymlink(path string) (string, error) { } // This command will give the target path of a given symlink // The -Force parameter will allow Get-Item to also evaluate hidden folders, like AppData. - cmd := fmt.Sprintf("(Get-Item -Force -LiteralPath %q).Target", upperpath) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).Target") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", upperpath)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return "", err }
890483394221Merge pull request #120130 from ritazh/cherry-pick-cve-2023-3676-1.27
1 file changed · +8 −4
pkg/volume/util/subpath/subpath_windows.go+8 −4 modified@@ -76,8 +76,10 @@ func getUpperPath(path string) string { // Check whether a directory/file is a link type or not // LinkType could be SymbolicLink, Junction, or HardLink func isLinkPath(path string) (bool, error) { - cmd := fmt.Sprintf("(Get-Item -LiteralPath %q).LinkType", path) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).LinkType") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", path)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return false, err } @@ -115,8 +117,10 @@ func evalSymlink(path string) (string, error) { } // This command will give the target path of a given symlink // The -Force parameter will allow Get-Item to also evaluate hidden folders, like AppData. - cmd := fmt.Sprintf("(Get-Item -Force -LiteralPath %q).Target", upperpath) - output, err := exec.Command("powershell", "/c", cmd).CombinedOutput() + cmd := exec.Command("powershell", "/c", "$ErrorActionPreference = 'Stop'; (Get-Item -Force -LiteralPath $env:linkpath).Target") + cmd.Env = append(os.Environ(), fmt.Sprintf("linkpath=%s", upperpath)) + klog.V(8).Infof("Executing command: %q", cmd.String()) + output, err := cmd.CombinedOutput() if err != nil { return "", err }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
17- github.com/advisories/GHSA-7fxm-f474-hf8wghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-3676ghsaADVISORY
- github.com/kubernetes/kubernetes/commit/073f9ea33a93ddaecdc2e829150fb715f6387399ghsaWEB
- github.com/kubernetes/kubernetes/commit/39cc101c7855341c651a943b9836b50fbace8a6bghsaWEB
- github.com/kubernetes/kubernetes/commit/74b617310c24ca84c2ec90c3858af745d65b5226ghsaWEB
- github.com/kubernetes/kubernetes/commit/890483394221c8f22e88c48f86cd4eaf4de65fd6ghsaWEB
- github.com/kubernetes/kubernetes/commit/a53faf5e17ed0b0771a605c6401ba4cbf297b59aghsaWEB
- github.com/kubernetes/kubernetes/issues/119339ghsaissue-trackingWEB
- github.com/kubernetes/kubernetes/pull/120127ghsaWEB
- github.com/kubernetes/kubernetes/pull/120129ghsaWEB
- github.com/kubernetes/kubernetes/pull/120130ghsaWEB
- github.com/kubernetes/kubernetes/pull/120131ghsaWEB
- github.com/kubernetes/kubernetes/pull/120132ghsaWEB
- github.com/kubernetes/kubernetes/pull/120133ghsaWEB
- groups.google.com/g/kubernetes-security-announce/c/d_fvHZ9a5zcghsamailing-listWEB
- security.netapp.com/advisory/ntap-20231130-0007ghsaWEB
- security.netapp.com/advisory/ntap-20231130-0007/mitre
News mentions
0No linked articles in our index yet.