01TL;DR — What Actually Gets Clusters Compromised
Your last audit passed. Your scanner shows green. Your Kubernetes cluster is wide open.
The CIS Kubernetes Benchmark lists over 200 controls. The NSA/CISA hardening guide runs 66 pages. Compliance teams treat all of them equally — one checkbox is one checkbox. Security engineers know better. An unrotated certificate is not the same as an unauthenticated API server. A missing label is not the same as etcd exposed on 0.0.0.0:2379.
CIS is a benchmark: precise, auditable, scanner-friendly, and strong at hardening components like API server, kubelet, etcd, and file permissions. NSA/CISA is hardening guidance: threat-driven and architecture-oriented, strong at supply chain, network segmentation, identity boundaries, and operational controls. Reality: many organizations "comply" while leaving the easiest compromise paths open.
02CIS vs NSA/CISA — What Each Framework Optimizes For
Both frameworks target Kubernetes security. They attack the problem from opposite directions. Treating them as interchangeable produces a compliance program optimized for neither threat prevention nor auditability.
| Dimension | CIS Benchmark | NSA/CISA Guidance |
|---|---|---|
| Scope | 120+ component-level controls | Threat-driven categories + reference architecture |
| Level structure | Level 1 / Level 2 | No levels — engineering judgment |
| Control plane hardening | Deep (flags, perms, certs) | Covered, less granular |
| Supply chain / image signing | Minimal | Explicit requirement |
| Network segmentation | Partial | Architecture-level |
| RBAC / IAM guidance | Present | Deeper blast-radius framing |
| Threat modeling context | Absent | Core design principle |
| Scanner / audit friendly | Optimized for evidence | Engineering judgment required |
| Best used for | Auditors, automated scanning, compliance evidence | Architecture decisions, leadership buy-in, threat modeling |
CIS goes deep where exact flags and permissions matter. NSA/CISA goes wide where architecture and threat context matter. If you run only CIS, you are still exposed to supply-chain pivots and lateral movement through flat networks. If you run only NSA/CISA, you lack the granular remediation evidence auditors require.
03Underrated Misconfigurations (High Real-World Impact)
These weaknesses are underweighted in compliance programs because they are harder to scan, hard to fix without breaking workloads, or dismissed as "platform not cluster." In incident response, they repeat. The data below is not CVSS — it is "how often this breaks you" combined with "how often you actually see it in production."
automountServiceAccountToken: true — every pod is a potential credential source.http://169.254.169.254, gets node credentials, accesses S3/IAM/RDS.04Overrated Controls (Effort >> Payoff)
Some controls get disproportionate attention because they are easy to measure or look impressive in audit reports. They are not useless — but they should not be your first milestone if you care about breach prevention and containment. Teams pass compliance by maximizing scanner score, while attackers still win through the same three routes: stolen identity → RBAC abuse, pod RCE → token abuse, flat network → lateral movement.
05Control Plane: The Root of All Trust
Every Kubernetes cluster has one control plane. Compromise it and you own everything — every node, every secret, every workload. The API server is the entry point. It is also the most misconfigured component in the wild.
--anonymous-auth=true allows unauthenticated requests to the API server. Combined with permissive RBAC, this is direct cluster compromise. CIS 1.2.1.--insecure-bind-address exposes an HTTP endpoint on localhost port 8080. Any process on the control plane node can issue unauthenticated API calls.--authorization-mode=AlwaysAllow — still found in the wild — grant every authenticated request full cluster access.yaml# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
containers:
- command:
- kube-apiserver
# Authentication
- --anonymous-auth=false
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
# Authorization
- --authorization-mode=Node,RBAC
# Admission control
- --enable-admission-plugins=NodeRestriction,PodSecurity,AlwaysPullImages
# Audit logging
- --audit-log-path=/var/log/audit.log
- --audit-log-maxage=30
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
# Disable insecure port
- --insecure-port=0
# etcd TLS
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
stat /etc/kubernetes/manifests/kube-apiserver.yaml — if you see 644 or world-readable, fix it now. Privilege escalation starts with readable manifests.
06etcd: The Brain, Unencrypted
etcd stores every Kubernetes object in plaintext by default. That means every Secret, every ServiceAccount token, every certificate request — all readable by anyone with etcd access. The CIS benchmark devotes an entire section to etcd because a single misconfigured endpoint is a full credential dump.
--encryption-provider-config, all Secrets are base64-encoded strings in etcd. Anyone who can read etcd has every credential in the cluster. CIS 1.2.34.07Worker Nodes: Where Execution Happens
Worker nodes run your workloads. They also run kubelet — the most privileged process outside the control plane. A misconfigured kubelet accepts unsigned webhook requests, allows anonymous API access, and can be coerced into executing arbitrary containers.
--anonymous-auth=true) + --authorization-mode=AlwaysAllow = unauthenticated code execution on any node. An attacker reaching port 10250 can exec into any pod, read all secrets from the node filesystem, and spawn new privileged containers. This combination was common in production clusters as recently as 2023.
authentication.anonymous.enabled: true allows unauthenticated access to the kubelet API. Combined with permissive authorization, this is remote code execution on any node. CIS 4.2.1.authorization.mode: Webhook, kubelet self-authorizes all requests. The RBAC policies you crafted on the API server have no effect on direct kubelet calls. CIS 4.2.3.yaml# /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false # CIS 4.2.1
webhook:
enabled: true # CIS 4.2.2
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook # CIS 4.2.3 - delegate to API server RBAC
readOnlyPort: 0 # CIS 4.2.4 - disable unauthenticated metrics
protectKernelDefaults: true # CIS 4.2.6
eventRecordQPS: 0
tlsCertFile: /var/lib/kubelet/pki/kubelet.crt
tlsPrivateKeyFile: /var/lib/kubelet/pki/kubelet.key
08RBAC, PSS, and Network Policies
Policy misconfigurations are the most common finding in Kubernetes security assessments. They are also the hardest to remediate after the fact — every change risks breaking production workloads. The three policy layers that matter most are RBAC bindings, Pod Security Standards enforcement, and network segmentation.
RBAC: Wildcards Kill
bash# Find ClusterRoles with wildcard permissions
kubectl get clusterroles -o json | jq '.items[] | select(.rules[]?.verbs[]? == "*") | .metadata.name'
# Find ClusterRoleBindings to cluster-admin
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name == "cluster-admin") | {name: .metadata.name, subjects: .subjects}'
# Find ServiceAccounts with automount enabled (the dangerous default)
kubectl get sa --all-namespaces -o json | jq '.items[] | select((.automountServiceAccountToken // true) == true) | {ns: .metadata.namespace, name: .metadata.name}'
# Find pods with unexpected SA token + network access to API server
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.automountServiceAccountToken != false) | {ns: .metadata.namespace, name: .metadata.name}'
yamlrules:
- apiGroups: ["*"]
resources: ["*"] # Full cluster access
verbs: ["*"]
yamlrules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
Pod Security Standards
PodSecurityPolicy was deprecated in 1.21 and removed in 1.25. Its replacement — Pod Security Admission (PSA) — enforces three built-in profiles via namespace labels. The NSA/CISA guide explicitly requires enforcing the restricted profile on all non-system namespaces.
No restrictions. Pods run as root, mount the host filesystem, use hostPID, hostNetwork. This is the default if no PSA label is set — a misconfigured namespace is a privileged namespace.
Blocks the most egregious misconfigurations: privileged containers, host namespace sharing, most dangerous volume types. Suitable for most workloads without modification.
The NSA/CISA recommended target. Requires non-root user, read-only root filesystem, drops all capabilities, blocks privilege escalation. Some legacy workloads will break — that is the point.
Label critical namespaces enforce=restricted, warn+audit others. Never label kube-system — it will break system workloads that legitimately need elevated privileges.
NetworkPolicy: Default Deny
yamlapiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # applies to all pods in namespace
policyTypes:
- Ingress
- Egress
# No rules = deny all. Add explicit allows per workload.
yaml- rule: ServiceAccount Token Read
desc: Detect process reading SA token from well-known mount path
condition: >
open_read and
fd.name startswith /var/run/secrets/kubernetes.io/serviceaccount and
not proc.name in (allowed_sa_consumers)
output: >
SA token read (user=%user.name proc=%proc.name
file=%fd.name ns=%k8s.ns.name pod=%k8s.pod.name)
priority: WARNING
tags: [T1078.004, k8s, rbac]
09NSA/CISA Gap Analysis: What CIS Misses
CIS Kubernetes Benchmark is a configuration posture guide. It tells you what flags to set, what file permissions to apply, what to enable and disable. What it does not cover is the operational security posture that NSA/CISA hardening guidance addresses: supply chain integrity, runtime detection, network encryption in transit, and workload identity at scale.
If your compliance program only covers CIS, you have a hardened attack surface with no detection capability. Attackers get in through supply chain compromise, move laterally through pod-to-pod traffic, and exfiltrate data over encrypted outbound connections your NetworkPolicy never blocked because you never implemented egress filtering for HTTPS:443.
yaml- rule: Container Escape via Namespace Enter
desc: Detect nsenter or chroot used to escape container namespace
condition: >
spawned_process and
proc.name in (nsenter, chroot, unshare) and
container.id != host
output: >
Potential container escape (user=%user.name proc=%proc.name
args=%proc.args pod=%k8s.pod.name ns=%k8s.ns.name)
priority: CRITICAL
tags: [T1611, container_escape, k8s]
10Customize Your Compliance Benchmark
"One benchmark fits all" is false. You customize by mapping controls to your threat model, blast radius, and operational constraints. Treat the benchmark as a control library, then classify each control into one of three tiers — not by CIS section number, but by what it actually blocks.
text# Score each control on five dimensions (0–5 each):
1) Exploitability reduction — does it remove a common attacker primitive?
2) Blast radius reduction — does it contain compromise to namespace/workload?
3) Coverage — does it protect many workloads/teams by default?
4) Operational cost — how hard to deploy and maintain without breaking apps?
5) Verifiability — can you continuously prove it (policy/audit evidence)?
Classify:
Mandatory (1+2+3) high, (4) manageable, (5) high
Recommended (1+2+3) medium-high, (4) medium-high, (5) medium
Suitable (1+2+3) variable, strongly context-dependent
restricted should be the default. Single-tenant clusters can tolerate baseline if workloads have legitimate privileged requirements — document and accept deviations explicitly.warn and audit modes for Pod Security Admission before enforce. Test admission controller changes against your full workload manifest set. A compliance change that takes down production erodes trust in the entire security program.11Security Roadmap vs Compliance Roadmap
Compliance is a snapshot. Security is a system. You do not win by "being compliant." You win by continuously shrinking attack paths and shortening detection and response time. Treat your security program like an engineering system with feedback loops — not a checklist you complete once a year.
bash# Identity / RBAC
# Find cluster-admin bindings (humans + CI service accounts)
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name == "cluster-admin") | .subjects'
# Detect wildcard roles: verbs: ["*"] or resources: ["*"]
kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.verbs[]? == "*") or (.resources[]? == "*")) | .metadata.name'
# Token discipline — find pods with automount enabled
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.automountServiceAccountToken != false) | "\(.metadata.namespace)/\(.metadata.name)"'
# Network containment — find namespaces with no NetworkPolicy
kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; do
count=$(kubectl get networkpolicies -n $ns --no-headers 2>/dev/null | wc -l)
[ "$count" -eq 0 ] && echo "NO POLICY: $ns"
done
# Run kube-bench and filter only FAIL findings
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl wait --for=condition=complete job/kube-bench --timeout=120s
kubectl logs job/kube-bench | grep -E '\[FAIL\]' | awk '{print $2, $3, $4, $5}'
kubectl delete job kube-bench
12Priority Tier Matrix: Security Over Compliance
Not every CIS control blocks a real attack. When you cannot fix everything at once, use this matrix — ranked by exploitability, blast radius, and operational feasibility.
automountServiceAccountToken: false by default. These controls block unauthenticated access — the fastest path to full cluster compromise.baseline enforced on all namespaces and restricted where feasible. Add NodeRestriction and AlwaysPullImages admission plugins. Implement default-deny NetworkPolicy across all application namespaces. Block IMDS/metadata access from pods. Disable ingress config snippets and audit annotations.Use CIS for the precision — auditable, scanner-friendly, granular flag-level controls that give your audit team evidence they can reproduce. Use NSA/CISA for the threat model — architecture-first thinking that tells you why controls matter and what attacker behavior they prevent. Then customize: classify every control as Mandatory, Recommended, or Suitable based on exploitability and blast radius in your environment, not checkbox comfort.
Compliance frameworks are a floor, not a ceiling. The controls that matter most — anonymous auth, RBAC wildcard removal, etcd encryption, default-deny networking, token discipline — are not the ones that take the most effort to implement. They take effort to justify because they break things. Breaking things in staging is how you build a cluster that does not break under attack. Every control you defer is a bet that your attacker has not read the same benchmark you have. They have. And they are checking faster than your scanner runs.
K8SEC continuously monitors your cluster posture against CIS, NSA/CISA, and runtime behavioral baselines — giving you the prioritized remediation queue your compliance scanner cannot.
Explore K8SEC on GitHub