VYPR
High severityNVD Advisory· Published Oct 31, 2023· Updated Feb 27, 2025

Kubernetes - Windows nodes - Insufficient input sanitization leads to privilege escalation

CVE-2023-3676

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.

PackageAffected versionsPatched versions
k8s.io/kubernetesGo
>= 1.28.0, < 1.28.11.28.1
k8s.io/kubernetesGo
>= 1.27.0, < 1.27.51.27.5
k8s.io/kubernetesGo
>= 1.26.0, < 1.26.81.26.8
k8s.io/kubernetesGo
>= 1.25.0, < 1.25.131.25.13
k8s.io/kubernetesGo
< 1.24.171.24.17

Affected products

66

Patches

5
a53faf5e17ed

Merge pull request #120133 from ritazh/cherry-pick-cve-2023-3676-1.24

https://github.com/kubernetes/kubernetesKubernetes Prow RobotAug 23, 2023via ghsa
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
     	}
    
073f9ea33a93

Merge pull request #120132 from ritazh/cherry-pick-cve-2023-3676-1.25

https://github.com/kubernetes/kubernetesKubernetes Prow RobotAug 23, 2023via ghsa
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
     	}
    
39cc101c7855

Merge pull request #120131 from ritazh/cherry-pick-cve-2023-3676-1.26

https://github.com/kubernetes/kubernetesKubernetes Prow RobotAug 23, 2023via ghsa
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
     	}
    
74b617310c24

Merge pull request #120129 from ritazh/cherry-pick-cve-2023-3676-1.28

https://github.com/kubernetes/kubernetesKubernetes Prow RobotAug 23, 2023via ghsa
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
     	}
    
890483394221

Merge pull request #120130 from ritazh/cherry-pick-cve-2023-3676-1.27

https://github.com/kubernetes/kubernetesKubernetes Prow RobotAug 23, 2023via ghsa
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

News mentions

0

No linked articles in our index yet.