4.6.3 default-namespace check false-positive FAIL: regex does not match kubectl's service/kubernetes output (aks-1.7/1.8, gke-1.8.0/1.9.0)
Overview
Check 4.6.3 "The default namespace should not be used (Automated)" reports FAIL on a cluster whose default namespace contains nothing but the built-in kubernetes Service. The audit tries to exclude that Service with a regex written for the legacy two-column kubectl layout (service kubernetes), but kubectl get all prints rows in resource/name form (service/kubernetes), so the exclusion never matches and the built-in Service itself is counted as "usage".
Affected profiles (identical audit line): aks-1.7, aks-1.8, gke-1.8.0, gke-1.9.0.
audit: |
output=$(kubectl get all -n default --no-headers 2>/dev/null | grep -v '^service\s\+kubernetes\s' || true)
if [ -z "$output" ]; then echo "DEFAULT_NAMESPACE_UNUSED"; else echo "DEFAULT_NAMESPACE_IN_USE"; fiHow did you run kube-bench?
As a Kubernetes Job on AKS (equivalent to job-aks.yaml, with a ServiceAccount that can get/list the kubectl get all resource kinds):
kube-bench run --targets node,policies --benchmark aks-1.8 --jsonWhat happened?
{"test_number":"4.6.3","status":"FAIL","actual_value":"DEFAULT_NAMESPACE_IN_USE", ...}while the namespace is empty apart from the API Service:
$ kubectl get all -n default --no-headers
service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 102dReproducing the audit's filter against that exact line:
$ echo 'service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 102d' | grep -v '^service\s\+kubernetes\s'
service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 102d # <- not filtered, so output is non-empty -> FAILWhat did you expect to happen:
PASS (DEFAULT_NAMESPACE_UNUSED), since no user workload exists in default.
Environment
- kube-bench
v0.16.0(imagedocker.io/aquasec/kube-bench:v0.16.0, which shipskubectlclient v1.36.1) - Kubernetes server v1.34.7 (AKS)
Running processes
Not relevant — this is a policies check that only depends on kubectl output formatting.
Configuration files
cfg/aks-1.8/policies.yaml, check 4.6.3 (and the same line in cfg/aks-1.7, cfg/gke-1.8.0, cfg/gke-1.9.0).
Anything else you would like to add:
Fix is a one-line regex change that accepts both output forms; PR to follow. Verified with the busybox grep in the kube-bench image:
$ printf '%s\n' 'service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 102d' | grep -Ev '^service(/|[[:space:]]+)kubernetes[[:space:]]'; echo $?
1 # built-in service filtered out
$ printf '%s\n' 'deployment.apps/my-app 1/1 1 1 3d' | grep -Ev '^service(/|[[:space:]]+)kubernetes[[:space:]]'; echo $?
deployment.apps/my-app 1/1 1 1 3d
0 # real workloads still detectedNot a duplicate of #1905, which is about the check returning WARN when kubectl is unavailable.
Source: aquasecurity/kube-bench