Kubernetes hardening: nine weaknesses a pentest lab exposes, and the policy that blocks each one
A walkthrough on a deliberately weak lab cluster — service-account token exposure, over-permissive RBAC bindings, host-path escapes — with the admission policy that closes each gap. For authorised testing on systems you own.
Authorised testing only. Everything below is performed on a deliberately weak lab cluster we own. Running these checks against a cluster you do not administer, or are not contracted to assess, is a criminal offence in most jurisdictions. Read our Disclaimer first.
Building a weak cluster and then hardening it teaches more than any checklist. Here are the nine gaps our lab exposes, each with the control that closes it.
Identity and tokens
1. Service-account tokens mounted by default. Every pod gets a token it usually does not need. Set automountServiceAccountToken: false on the default service account in each namespace, and opt in only where a workload genuinely talks to the API.
2. Long-lived tokens in secrets. Bound service-account tokens expire and are tied to a pod. Prefer projected volumes with an audience and expiry over static secret-based tokens.
3. The default service account carrying real permissions. It should carry none. Give each workload its own service account and bind roles to that.
RBAC
4. Wildcards in role rules. A role granting on is a cluster-admin in disguise. Enumerate the verbs and resources a workload actually uses and grant those.
5. Bindings to groups nobody audits. system:authenticated shows up in bindings more often than anyone expects, which grants everyone who can authenticate. Review every ClusterRoleBinding subject.
6. Escalation paths through secrets. Read access to secrets in a namespace is read access to every credential in it. Treat get secrets as a privileged verb.
Workload isolation
7. Host-path mounts. A pod mounting the host filesystem can read kubelet credentials and escape to the node. Block host paths in admission policy, with an explicit allowlist for the handful of system workloads that need them.
8. Privileged and hostNetwork pods. Both dissolve the boundary between pod and node. The Pod Security Standards restricted profile refuses them, and enforcing that profile namespace-by-namespace is the single highest-value change most clusters can make.
9. No egress policy. A compromised pod that can reach the internet can exfiltrate and pull tooling. Default-deny egress, then allow what each namespace needs.
The order that matters
Do not start with the exotic controls. In our experience the sequence that removes the most risk per hour of work is:
- Enforce the restricted Pod Security Standard on application namespaces.
- Remove wildcard RBAC rules and audit
system:authenticatedbindings. - Turn off default token automounting.
- Add default-deny network policies, then open what breaks.
Everything else is refinement on top of those four.