
TL;DR — What are the Kubernetes security controls that actually matter? Four layers decide most real-world cluster compromises: RBAC (who can do what in the API), pod security (what a workload may touch), network policy (what may talk to what), and the image supply chain (what is running at all). Get those right with Kubernetes’ own mechanisms — least-privilege bindings, Pod Security Admission in restricted mode, default-deny policies, signed and scanned images — and you remove the paths behind the overwhelming majority of cluster incidents. This is the fundamentals map, with the verification step for each control.
Kubernetes is the operating system of most cloud infrastructure in 2026, and its security failures are boringly consistent: an over-privileged service account, a privileged pod, a flat network, an unverified image. Not zero-days — misconfigurations. The good news is that the platform has absorbed its own hardest lessons (Pod Security Admission replaced the deprecated PodSecurityPolicy; long-lived node tokens are gone; admission ecosystems matured). This post walks the four layers that matter, in the order an attacker would touch them.
The threat model in one picture: an attacker lands as either a workload (compromised app, malicious dependency — see our supply-chain coverage) or an identity (leaked kubeconfig, CI pipeline with cluster-admin). From there they escalate through exactly the four layers below. Every control in this post breaks one of those hops.
Layer 0: The Control Plane Itself
Before workloads, the servers running the cluster deserve their own pass, because owning the API server ends the game in one hop:
- Exposure. The API server belongs on a controlled network path with an authenticated ingress in front of it — never naively exposed to the internet with permissive anonymous settings. Kubelet ports (10250) and the etcd cluster (2379) are not internet-facing services; treat any public reachability as a critical finding.
- etcd. It holds every secret and every object. Client certificate authentication, TLS in transit, encryption at rest for secrets, and access restricted to the control plane. Reading an unencrypted etcd snapshot is the whole cluster in one file.
- Kubelet authorization. Anonymous authentication off and webhook authorization mode on — the kubelet API is a popular post-exploitation path precisely because hardening it is forgotten.
- Audit logging. A configured audit policy capturing authentication failures and authorization denials is the difference between investigating an incident and guessing about one. Log where you’ll actually look.
Layer 1: RBAC — The API Is the Castle
Everything in Kubernetes is an API call, so authorization is the perimeter. The model is small: Role/ClusterRole define verbs on resources; RoleBinding/ClusterRoleBinding attach them to users, groups, or service accounts. The failures are equally small and extremely common:
- cluster-admin in CI. The deployment pipeline uses one kubeconfig with full rights, so any code-execution in the pipeline is instant cluster ownership. Pipelines should get namespace-scoped roles, with a separate break-glass credential.
- Wildcard verbs and resources.
apiGroups: ["*"], resources: ["*"], verbs: ["*"]appears in countless copy-pasted manifests. Treat any wildcard binding as a finding. - Shared default service accounts. Every namespace has one, every pod mounts one by default, and any bound permissions apply to every workload that forgot to set
serviceAccountName. Create one service account per workload and setautomountServiceAccountToken: falsewhere the API isn’t needed — long-lived auto-mounted tokens have been on the way out since Kubernetes 1.24, but only if you stop opting back in. - Unaudited bindings. RBAC sprawls because nothing prunes it. Review bindings like access reviews: who holds create pods, exec, secrets get, or nodes/proxy — and why.
The one-line audit that finds most sins: list all ClusterRoleBindings, then all RoleBindings per namespace, and reject anything binding cluster-admin to a service account or CI identity.
Layer 2: Pod Security — What a Workload May Touch
The old PodSecurityPolicy was notoriously difficult — removed in Kubernetes 1.25, replaced by Pod Security Admission: namespace labels that enforce a profile on every pod admitted to that namespace. The three levels:
| Level | Blocks | Use for |
|---|---|---|
| privileged (enforced) | Nothing — maximum access | Nothing, ideally. Specific system namespaces only |
| baseline | hostNetwork, hostPID, hostPath, added capabilities, privileged containers | Minimum acceptable floor for any multi-tenant cluster |
| restricted | Baseline + requires runAsNonRoot, dropped capabilities, seccomp profiles, read-only root filesystem friendliness | The default target for application workloads |
Run baseline at minimum cluster-wide; label application namespaces enforce=restricted with warn and audit modes enabled first, then tighten. The workload-level companions that make “restricted” achievable: run as non-root with a dropped capability set, securityContext.seccompProfile: RuntimeDefault, no host namespaces, and resource requests/limits on everything — resource exhaustion is a denial-of-service class the kernel handles badly without limits.
Layer 3: Network Policy — The Flat Network Is a Bug
Default Kubernetes networking allows every pod to reach every pod, across every namespace, in the cluster. That means a compromised frontend pod can port-scan the database namespace, hit kube APIs of adjacent services, and exfiltrate over any egress it likes. NetworkPolicy fixes the default:
- Default-deny ingress and egress in every application namespace — two one-line policies that convert “any” to “none”.
- Allow-list the real flows: frontend→backend on its port, backend→database on its port, DNS.
- Control egress — the step most shops skip. Restricting outbound traffic to required destinations kills a whole exfiltration and command-and-control class at the workload layer.
Caveats that matter: NetworkPolicy is enforced by the CNI plugin, and behavior varies (some plugins have partial egress support); policies are additive; and nothing about NetworkPolicy encrypts anything — for transport security you want mTLS via a service mesh where the data warrants it. But the default-deny skeleton alone removes the lateral movement that turns one compromised pod into a cluster-wide incident.
Layer 4: The Image Supply Chain — What Runs at All
The final layer is the payload itself:
- Pinned, verified images. Digest-pinned bases (not
:latest), pulled from registries you control, verified by signature — Sigstore/cosign signing wired into admission so only images your pipeline signed can run. - Policy-as-code admission. Kyverno or OPA Gatekeeper rules encoding “no
latest“, “no privileged”, “resource limits required”, “image must be signed” — the same controls above, enforced at the API server instead of hoped for in review. - Scanning with an SBOM behind it. Vulnerability scanning that triages against a real component inventory — our companion piece on SBOMs in practice covers building that pipeline properly.
- Secrets discipline. Kubernetes Secrets are only as protected as your etcd encryption-at-rest configuration and RBAC around
get secrets; for anything serious, external secret management (KMS/Vault-backed) beats environment-variable sprawl, and GitOps flows should never commit plaintext.
The Ten-Point Audit Checklist
| # | Control | Verification |
|---|---|---|
| 1 | No cluster-admin for CI or service accounts | Audit ClusterRoleBindings; break-glass is human-only |
| 2 | One service account per workload | No pod on the default SA with bound permissions |
| 3 | API tokens not auto-mounted unless needed | automountServiceAccountToken: false as the namespace default |
| 4 | Pod Security: baseline minimum, restricted for apps | Namespace labels present; privileged pods rejected |
| 5 | Non-root, dropped capabilities, seccomp RuntimeDefault | Restricted-profile pods pass admission |
| 6 | Resource limits on every container | Admission policy rejects limit-less pods |
| 7 | Default-deny ingress + egress per namespace | Cross-namespace probe fails; only allow-listed flows succeed |
| 8 | Images digest-pinned and signature-verified | Unsigned image admission fails |
| 9 | etcd encryption at rest; secrets RBAC tight | etcd snapshot does not yield plaintext secrets |
| 10 | API audit logging on; CIS benchmark passing | kube-bench run; audit log covers authz denials |
Key Takeaways
- Kubernetes incidents are overwhelmingly misconfigurations across four layers: RBAC, pod security, network policy, image supply chain.
- RBAC: no cluster-admin for machines, one service account per workload, no unnecessary token mounts, and continuous binding audits.
- Pod Security Admission (baseline/restricted) replaced PodSecurityPolicy — enforce restricted for application namespaces via warn/audit first.
- The cluster network is flat by default; default-deny ingress and egress policies are the cheapest high-value control in the platform.
- Supply chain: digest-pinned, signed images with policy-as-code admission turn your controls into API-enforced guarantees.
- Validate with the CIS Kubernetes Benchmark and audit logs — a control you don’t verify is a hope, not a control.
FAQ
Is Kubernetes secure by default?
No — it is secure by configuration. Defaults optimize for onboarding speed: flat networking, permissive admission, default service accounts. Each default is documented and each has a hardening counterpart in this post.
What replaced PodSecurityPolicy?
Pod Security Admission — namespace labels enforcing the privileged/baseline/restricted profiles at admission time. PSP was deprecated and removed in Kubernetes 1.25.
Do I need a service mesh for security?
Not for the fundamentals. Default-deny NetworkPolicy handles segmentation; meshes add mTLS and identity when you need transport security between services and are prepared to operate the extra layer.
What is the first thing to check on an existing cluster?
ClusterRoleBindings for cluster-admin held by service accounts or CI, then whether any namespace lacks a default-deny network policy. Those two audits surface most of the risk in minutes.
Are Kubernetes Secrets safe to use?
With etcd encryption at rest, tight RBAC on secret reads, and no plaintext-in-Git: adequate for most workloads. High-assurance secrets belong in a KMS- or Vault-backed store with short-lived credentials.
How do I benchmark my cluster’s configuration?
Run the CIS Kubernetes Benchmark (kube-bench automates it) and track exceptions deliberately — the benchmark is the checklist, your risk register is the decider.
References
- Kubernetes documentation — Using RBAC Authorization
- Kubernetes documentation — Pod Security Standards; Pod Security Admission
- Kubernetes documentation — Network Policies
- CIS — Kubernetes Benchmark (CIS Benchmarks collection)
- Sigstore — image signing and verification; Kyverno and OPA Gatekeeper — policy-as-code admission
- hmmnm.com — SBOMs in Practice: SPDX vs CycloneDX and What Actually Breaks
Current as of September 2026 · controls verified against current Kubernetes documentation.
Educational reference only — match controls to your cluster version and threat model.
Author: hmmnm.com editorial team · hmmnm.com
