diff --git a/checkov/kubernetes/checks/resource/k8s/RootContainersHighUID.py b/checkov/kubernetes/checks/resource/k8s/RootContainersHighUID.py index c8f5aaef34..5cc7945390 100644 --- a/checkov/kubernetes/checks/resource/k8s/RootContainersHighUID.py +++ b/checkov/kubernetes/checks/resource/k8s/RootContainersHighUID.py @@ -21,6 +21,12 @@ def scan_spec_conf(self, conf: dict[str, Any]) -> CheckResult: # Collect results if spec and isinstance(spec, dict): + # With a private user namespace (hostUsers: false) container UIDs are + # remapped to unprivileged host UIDs, so the high-UID host-collision + # concern this check guards against no longer applies. + if spec.get("hostUsers") is False: + return CheckResult.PASSED + results: dict[str, Any] = {"pod": {}, "container": []} results["pod"]["runAsUser"] = self.check_runAsUser(spec, 10000) diff --git a/tests/kubernetes/checks/example_RootContainersHighUID/rootContainersHighUIDFAILED.yaml b/tests/kubernetes/checks/example_RootContainersHighUID/rootContainersHighUIDFAILED.yaml index 1ce793b7ad..1e0583d726 100644 --- a/tests/kubernetes/checks/example_RootContainersHighUID/rootContainersHighUIDFAILED.yaml +++ b/tests/kubernetes/checks/example_RootContainersHighUID/rootContainersHighUIDFAILED.yaml @@ -88,3 +88,16 @@ spec: - name: main2 image: alpine command: ["/bin/sleep", "999999"] +--- +# hostUsers: true keeps the host user namespace, so the high-UID check still +# applies and a missing runAsUser must FAIL (guards the hostUsers exemption) +apiVersion: v1 +kind: Pod +metadata: + name: pod5 +spec: + hostUsers: true + containers: + - name: main + image: alpine + command: ["/bin/sleep", "999999"] diff --git a/tests/kubernetes/checks/example_RootContainersHighUID/rootContainersHighUIDPASSED.yaml b/tests/kubernetes/checks/example_RootContainersHighUID/rootContainersHighUIDPASSED.yaml index aa8de542d4..0338c8da3f 100644 --- a/tests/kubernetes/checks/example_RootContainersHighUID/rootContainersHighUIDPASSED.yaml +++ b/tests/kubernetes/checks/example_RootContainersHighUID/rootContainersHighUIDPASSED.yaml @@ -38,3 +38,16 @@ spec: command: ["/bin/sleep", "999999"] securityContext: runAsUser: 12000 +--- +# runAsUser not set, but hostUsers: false enables a private user namespace, +# so host UID collisions cannot occur (PASSED) +apiVersion: v1 +kind: Pod +metadata: + name: pod4 +spec: + hostUsers: false + containers: + - name: main + image: alpine + command: ["/bin/sleep", "999999"] diff --git a/tests/kubernetes/checks/test_RootContainersHighUID.py b/tests/kubernetes/checks/test_RootContainersHighUID.py index 0fca549458..1f7a1d1f8f 100644 --- a/tests/kubernetes/checks/test_RootContainersHighUID.py +++ b/tests/kubernetes/checks/test_RootContainersHighUID.py @@ -16,8 +16,8 @@ def test_summary(self): report = runner.run(root_folder=test_files_dir,runner_filter=RunnerFilter(checks=[check.id])) summary = report.get_summary() - self.assertEqual(summary['passed'], 3) - self.assertEqual(summary['failed'], 6) + self.assertEqual(summary['passed'], 4) + self.assertEqual(summary['failed'], 7) self.assertEqual(summary['skipped'], 0) self.assertEqual(summary['parsing_errors'], 0)