What is Kubernetes security?
Kubernetes security is the practice of hardening a container orchestration cluster and the workloads running on it. Because a single API server governs scheduling, access and configuration for the whole cluster, the discipline focuses on role-based access control, workload security context, network policy, image provenance, secrets handling, and node and control-plane baselines.
Three published references cover most of this ground. The CIS Kubernetes Benchmark is the checkable configuration baseline, with separate versions for vanilla Kubernetes and for EKS, AKS, GKE and OpenShift. The OWASP Kubernetes Top Ten ranks the risks by how often they cause real harm, and the OWASP Kubernetes Security Cheat Sheet gives the implementation detail behind each control.
For the container layer beneath the orchestrator, NIST SP 800-190 remains the standard treatment of image, registry and runtime risk. Joint guidance from CISA and the NSA, the Kubernetes Hardening Guide, pulls the cluster and container layers together into one set of recommendations.
Why Kubernetes security works differently
A traditional network has many separate boundaries: a firewall here, a VLAN there, a server that is patched or is not. Kubernetes concentrates a huge amount of that decision-making behind a single control point, the API server, which every workload, every deployment pipeline and every operator interacts with. Get the configuration of that one control point wrong, and the blast radius is the whole cluster, not one machine.
This is also why Kubernetes security cannot be reduced to patching nodes. Role-based access control, workload configuration, network policy, the provenance of the container images being run, and how secrets are handled all sit above the operating system layer, inside the cluster's own configuration. A perfectly patched node running a privileged, over-permissioned workload is still an open door.
It also changes what an attacker does after landing. MITRE maintains a Containers matrix specifically for techniques that target container platforms and orchestrators, which is a useful reminder that container escape, service account token abuse and cluster-wide discovery are catalogued behaviours rather than theoretical ones.
The core areas of Kubernetes security best practice
Most real-world Kubernetes hardening work falls into a handful of areas. Each one addresses a different way the cluster's power can be misused if left at default settings.
Role-based access control (RBAC) and least privilege
RBAC controls who and what can do which actions against the Kubernetes API: which service accounts can list secrets, which users can create pods, which roles can modify cluster-wide resources. The most common failure mode is over-broad bindings: a cluster-admin role bound to something that only ever needed read access to one namespace, left in place because it worked and nobody revisited it.
A few verbs deserve particular attention because they convert limited access into broad access. The ability to create pods in a namespace is effectively the ability to run code as any service account in that namespace; read access to secrets exposes whatever those secrets protect; and escalate, bind and impersonate let a principal grant itself rights it was not given. Treat all of them as privileged assignments.
- Grant the narrowest role that lets a workload or user do its job.
- Prefer namespace-scoped roles over cluster-wide ones by default.
- Treat create pods, read secrets, escalate, bind and impersonate as privileged.
- Review bindings periodically; unused broad access accumulates silently.
An indicative read-only ClusterRole
Auditing a cluster does not require write access to it. The following is an indicative sketch of a read-only ClusterRole rather than a deployable manifest, shown to make the shape of a least-privilege role concrete.
- apiVersion: rbac.authorization.k8s.io/v1 with kind: ClusterRole
- metadata.name: readonly-auditor
- rules[0].apiGroups: the core group as an empty string, plus apps, rbac.authorization.k8s.io and networking.k8s.io
- rules[0].resources: pods, deployments, daemonsets, roles, rolebindings, clusterroles, clusterrolebindings, networkpolicies
- rules[0].verbs: get, list and watch, and nothing else
Verifying a role instead of trusting it
What makes that role read-only is the verb list. Nothing in it grants create, update, patch, delete, escalate or impersonate, and it deliberately omits secrets, whose contents a configuration review does not need. Naming the resources explicitly matters too: a wildcard entry quietly expands to cover custom resources added later.
Bind it with a ClusterRoleBinding, then check the result rather than the manifest. Running kubectl auth can-i --list --as=system:serviceaccount:default:readonly-auditor prints what the binding actually permits, including anything inherited from another binding the same subject already had, which is the usual source of surprises.
Pod security and workload configuration
A pod's security context determines how much of the underlying node it can touch. Privileged containers, containers that run as root by default, and pods granted host networking, host process namespace or host filesystem access all step outside the isolation Kubernetes is supposed to provide, sometimes for a legitimate reason, often out of habit or an unreviewed default.
The settings that carry most of this are a small set of fields on the pod or container: privileged, hostNetwork, hostPID, hostIPC, allowPrivilegeEscalation, runAsNonRoot and readOnlyRootFilesystem. Enforcing them centrally, rather than asking every team to remember, is what Pod Security admission is for; its restricted profile denies the dangerous combinations by default at the namespace level.
- Run containers as a non-root user with a read-only root filesystem where possible.
- Set allowPrivilegeEscalation to false and drop all Linux capabilities, adding back only what is needed.
- Avoid privileged pods and host namespace access unless explicitly required.
- Enforce a baseline centrally through admission control rather than per-team convention.
Network policy and segmentation
Without a network policy, Kubernetes defaults to allowing all pods in a cluster to talk to all other pods. That default is convenient during development and dangerous in production: a single compromised workload can reach every other workload in the cluster with no further effort.
A default-deny policy is short: a NetworkPolicy whose podSelector is empty, so it selects every pod in the namespace, and whose policyTypes lists Ingress and Egress with no rules underneath. Everything is then denied in that namespace until an explicit allow policy opens a path. Applying egress as well as ingress is the part most often skipped, and it is the half that limits what a compromised pod can reach outward.
- Apply a default-deny policy covering both ingress and egress per namespace.
- Open only the traffic actually needed, named by selector rather than by IP range.
- Segment namespaces so a compromise in one workload cannot freely reach another.
- Confirm the cluster's network plugin actually enforces policy; some accept it silently.
Image provenance and supply chain
Every workload in the cluster runs from a container image, and that image is only as trustworthy as where it came from and what has changed in it since it was built. Pulling images from unverified sources or floating tags that can change underneath a deployment without warning introduces risk that has nothing to do with the cluster's own configuration.
Digest pinning is the concrete control. A deployment referencing an image by a tag such as :latest resolves to whatever that tag points at when the pod happens to be scheduled, which may not be what was tested; referencing it by sha256 digest resolves to exactly one image every time. NIST SP 800-190 covers the wider registry and runtime considerations that sit around this.
- Pull images only from trusted, controlled registries.
- Pin deployments to an image digest rather than a mutable tag.
- Set imagePullPolicy deliberately rather than relying on the default.
- Scan images for known vulnerabilities before they reach production.
Secrets management
Kubernetes Secrets are more accessible than most teams expect: by default they are base64-encoded, not encrypted, and any workload or user with the right RBAC permission can read them. Credentials committed straight into a pod's environment variables or into a manifest checked into source control are a routine finding, not a rare one.
Two settings reduce the exposure meaningfully. Encryption at rest for the Secrets store means an etcd backup is not a plaintext credential dump. Setting automountServiceAccountToken to false on workloads that never call the Kubernetes API removes a token that would otherwise sit inside every container, ready to be used by anything that achieves code execution there.
- Restrict who and what can read secrets through RBAC, not obscurity.
- Enable encryption at rest for the Secrets store.
- Set automountServiceAccountToken to false where the API is not needed.
- Never commit credentials into manifests or images; inject them at runtime instead.
Node and control-plane hardening
Below the workload layer, the nodes and control plane themselves need hardening: kubelet configuration, API server flags, etcd access controls and file permissions. The CIS Kubernetes Benchmark is the standard reference baseline for this layer, covering the control plane, the kubelet, and policy configuration in a structured, checkable form.
Several of its highest-value checks are single flags. The API server should not run with --anonymous-auth=true, its authorisation mode should include RBAC rather than AlwaysAllow, and the kubelet's read-only port should be disabled so node and pod metadata is not served unauthenticated. Etcd deserves particular care, since read access to it is equivalent to read access to every secret in the cluster.
- Baseline node and control-plane configuration against the CIS Kubernetes Benchmark.
- Disable anonymous authentication and the kubelet read-only port.
- Restrict direct access to etcd to the control plane only, and encrypt its backups.
- Keep the Kubernetes version and kubelet current with supported patches.
Managed clusters change how you enforce some of this
Most production Kubernetes today runs on a managed offering such as GKE, EKS or AKS, or a distribution such as OpenShift or k3s, rather than fully self-managed nodes. RBAC, pod security, network policy, image provenance and secrets handling still apply exactly as described above; they are configuration you control regardless of who runs the underlying infrastructure.
Node and control-plane hardening is where things diverge. On a fully managed runtime such as GKE Autopilot or EKS Fargate, host-level pods are not permitted at all, because the cloud provider owns and hardens the node layer as part of the service. In that model, node and control-plane CIS checks are more appropriately handled through the cloud provider's own configuration audit rather than a job running inside the cluster, while the API-level checks above still run normally over the cluster's API.
This is why CIS publishes distribution-specific benchmarks rather than one document. The EKS, AKS, GKE and OpenShift editions drop or restate the checks that do not apply where the provider owns the control plane, so assessing a managed cluster against the vanilla Kubernetes benchmark produces failures that nobody can act on.
| Cluster type | Node-level CIS checks | API posture review |
|---|---|---|
| Self-managed or on-prem | Runs directly against nodes | Runs as normal |
| GKE Standard | Runs directly against nodes | Runs as normal |
| EKS with a nodegroup | Runs directly against nodes | Runs as normal |
| AKS | Runs directly against nodes | Runs as normal |
| OpenShift, k3s | Runs directly against nodes | Runs as normal |
| GKE Autopilot | Routed through the cloud configuration audit | Runs as normal |
| EKS Fargate | Routed through the cloud configuration audit | Runs as normal |
How these weaknesses combine in a real compromise
As with most infrastructure security, no single misconfiguration above tends to be catastrophic in isolation. The risk is in how they combine. A realistic path starts with a single workload that has been given a broad, cluster-wide RBAC role for convenience during initial setup and never revisited once the application went into production.
That workload also runs as root with no restriction on host access, because the base image it was built from defaulted to it and nobody changed it. If an application-level flaw in that workload lets an attacker execute commands inside the container, the mounted service account token plus the over-broad RBAC role give them a way to query the Kubernetes API directly rather than staying trapped inside one pod.
With no network policy in place, that same access lets the attacker reach every other pod in the cluster, including one that reads a Secret containing a cloud credential because nothing restricted which service accounts could read it. From there, the compromise moves outside the cluster entirely, into the cloud account backing it. Every step in that chain used a default that was left unreviewed, not a novel technique.
This is why an audit that only lists individual misconfigured settings understates the real risk. Understanding how RBAC, pod security, network policy and secrets exposure interact is what turns a list of findings into an honest picture of what an attacker could actually reach.
A practical checklist
A short reference for what good looks like across each area covered above.
| Area | Good practice |
|---|---|
| RBAC | Narrowest role for the job; broad bindings reviewed regularly |
| Pod security | Non-root, read-only filesystem, no unneeded host access |
| Network policy | Default-deny on ingress and egress, explicit allows |
| Image provenance | Trusted registries, digest pinning, pre-deploy scanning |
| Secrets | RBAC-restricted, encrypted at rest, never in source control |
| Service account tokens | Not automounted unless the API is genuinely used |
| Node and control plane | Baselined against the CIS Kubernetes Benchmark |
| Managed runtimes | Distribution-specific benchmark, not the vanilla one |
How PentestOps helps
PentestOps audits Kubernetes clusters agentlessly, using a customer-supplied read-only kubeconfig with no agent and no DaemonSet to install. The platform verifies connectivity and detects the distribution automatically before any check runs, and covers GKE (including Autopilot), EKS (including Fargate), AKS, OpenShift, k3s, and self-managed or on-prem clusters through the same onboarding flow.
Two layers run for every cluster. An API posture review covers RBAC, workload security context, privileged and host pods, capabilities, network policy and image provenance over the kubeconfig, spanning 83 Kubernetes API and RBAC checks. Where the cluster permits host-level access, node and control-plane CIS Kubernetes Benchmark checks run as a short-lived, auto-cleaned job inside the cluster; on fully managed runtimes such as GKE Autopilot or EKS Fargate, that layer is routed through the cloud configuration audit instead, exactly as described above.
Findings map to 8 compliance reporting frameworks (OWASP Top 10, PCI DSS v4.0, NIST 800-53, SOC 2, HIPAA, GDPR, ISO 27001, SMB1001) plus CIS Benchmarks for AWS, Azure, GCP and Kubernetes. See Kubernetes security testing for the full detail, or cloud penetration testing for the account the cluster runs in.
To see it against your own cluster, run a free demo scan or start a trial: all paid plans start with a 7-day free trial, and a card is required to start your trial and is only charged after the trial ends, unless you cancel first.