Kubernetes security: the most exploited mistakes and how to audit a cluster

By Kike Gandia · Co-Founder & CEO, OSCP

Kubernetes is not insecure, but its defaults put getting things working ahead of isolating them: pods talk to each other without restriction, secrets are stored unencrypted in etcd and audit logging does not switch itself on. Add broad RBAC permissions and privileged pods, and a vulnerability in a single application can end in control of the cluster and, on a managed service, of part of the cloud account. This guide covers the most exploited mistakes, what changes on EKS, AKS and GKE, and how a cluster is audited both against a baseline and from an attacker's point of view.

Why a Kubernetes cluster is a different kind of target

A Kubernetes cluster is, above all, an API. Whoever controls the API server controls every workload, every secret and often the cloud credentials the nodes work with. That is why an attacker's goal is usually not the application itself but using it as a way into the control plane.

There are three usual starting points:

  • From outside: an API server, an admin dashboard or the kubelet port exposed to the internet with weak or no authentication.
  • From a compromised container: a remote code execution flaw in an application gives a shell inside a pod. From there the attacker tries the service account token, the internal network, the cloud metadata service and the chance of escaping to the node.
  • From the delivery chain: a kubeconfig on a developer's laptop or the CI/CD pipeline's credentials, which usually have permission to deploy anything.

The case that made it famous was Tesla in 2018: according to RedLock's research team, attackers got into a Kubernetes console that was not password protected, found AWS credentials in a pod with access to an S3 bucket and used the cluster to mine cryptocurrency.

For years the official documentation summed up security in four layers, the “4Cs”: cloud, cluster, container and code. The English documentation now organises it by lifecycle phase (develop, distribute, deploy and runtime), but the underlying idea still holds: each layer depends on the one below, and a well-hardened cluster on a weak cloud account is not secure.

The most exploited mistakes at a glance

MistakeWhy it is seriousHow it is detected
Excessive RBACService accounts or users with permissions equivalent to cluster adminReview of roles and bindings, analysis of who can do what
Privileged pods or host accessA compromised container escapes to the node and, from there, to other podsPod Security Admission, admission policies, CIS Benchmark
Network without NetworkPoliciesA compromised pod reaches databases, internal APIs and the control planePolicy review and a reachability test from a pod
Unencrypted or misplaced secretsWhoever reads etcd, a backup or a repository gets credentialsAPI server configuration, review of manifests and repositories
Pods reaching the node's cloud roleA shell in a pod turns into cloud account credentialsTesting the metadata service from a pod
Exposed componentsAPI server, dashboards or kubelet reachable without proper authenticationExternal scanning and configuration review
Vulnerable or retired componentsAn ingress controller or an image with critical flaws gives access to the clusterVersion inventory and image scanning
No audit loggingNo way of knowing what an attacker did or of detecting it in timeAPI server or managed service configuration

The following sections explain each block and what to check.

RBAC: the permissions that amount to being an admin

Kubernetes role-based access control (RBAC) is powerful, but some permissions that look narrow allow escalation. The project's own RBAC good practices guide lists them:

PermissionWhy it is dangerous
get, list or watch on secretsListing or watching secrets also reveals their contents, not just their names
Creating pods or resources that manage them (deployments, jobs…)Grants implicit access to the namespace's secrets, ConfigMaps and service accounts; a privileged pod reaches the node
Creating persistent volumesAllows mounting node paths (hostPath) and reading its file system
get on nodes/proxyNot read-only: it allows running commands in the node's pods while bypassing auditing and admission control
escalate and bind verbsAllow creating or binding roles with permissions the user does not have
impersonate verbAllows acting as another user or service account
Approving certificate signing requests (CSRs)Allows issuing client certificates with arbitrary names, including those of system components
Creating service account tokensAllows obtaining tokens for existing service accounts, with their permissions
Managing admission webhooksWhoever controls them can read and modify the objects created in the cluster
Modifying namespacesChanging their labels can switch off the Pod Security level or change what network policies apply to

On top of that come the configuration mistakes that keep appearing in reviews:

  • cluster-admin bound to an application's service account or to the deployment pipeline's user “to make it work”.
  • Wildcards in verbs or resources (*), which also grant whatever is added in the future.
  • The service account token mounted in every pod, even when the application never calls the API server. It is the first thing anyone who gets a shell in a pod tries.
  • Roles inherited from tools —operators, dashboards, monitoring agents— installed with broad permissions and never reviewed.

The basic check is to ask the cluster itself what each identity can do, starting with the service accounts of internet-facing applications.

Pod security: privileges, Pod Security Standards and admission

A container is not a virtual machine: it shares the kernel with the node. Some configuration options break whatever isolation is left:

  • privileged: true: the container has practically the same permissions as a root process on the node.
  • hostPath: mounts node directories inside the container; depending on the path, it allows reading kubelet credentials or writing to the system.
  • hostNetwork, hostPID or hostIPC: the container sees the node's network, processes or shared memory.
  • Added Linux capabilities, such as SYS_ADMIN, and the ability to escalate privileges inside the container.
  • Running as root without needing to.

To prevent this systematically, Kubernetes defines three levels, the Pod Security Standards:

LevelWhat it allowsWhen to use it
PrivilegedUnrestrictedOnly system components that need it, such as some network or storage agents
BaselineMinimal restrictions that prevent known privilege escalationsThe reasonable minimum for any application
RestrictedHeavy restrictions, following current pod hardening best practicesThe target for your own applications

They are applied with Pod Security Admission, stable since Kubernetes 1.25, through labels on each namespace with three modes: enforce (reject), audit (log) and warn (notify). Its predecessor, PodSecurityPolicy, was removed in that same version: a cluster that relied on it and was upgraded without replacing it may have lost its controls without anyone noticing. For finer-grained rules —allowed image registries, mandatory labels, resource limits— policy engines such as Kyverno or OPA Gatekeeper are used.

Networking: by default, everything talks to everything

The official documentation is explicit: by default, a pod is not isolated and accepts all inbound connections, and the same applies to outbound traffic. NetworkPolicies change that, with an important caveat: they only work if the cluster's network plugin (CNI) implements them. Creating a policy in a cluster whose CNI does not support them has no effect at all.

Without network policies, a compromised pod can:

  • Connect to the databases, caches and queues of any namespace.
  • Call internal APIs designed on the assumption that only other trusted services would use them.
  • Reach the cloud provider's metadata service and other node services.
  • Go out to the internet to download tools or exfiltrate data.

The recommended pattern is to deny everything by default in each namespace and open only the flows that are needed, including egress: most applications have no need to reach the metadata service or the internet.

The ingress controller deserves separate attention, because it receives internet traffic and usually has broad permissions. In March 2025 the project published CVE-2025-1974 in ingress-nginx, with a CVSS score of 9.8: according to the official Kubernetes blog, anything on the pod network had a good chance of taking over the cluster with no credentials, partly because ingress-nginx has access to all secrets by default. Its retirement was announced in November 2025, and maintenance ended in March 2026: if your cluster still uses it, it will no longer receive security patches and you should plan the migration, for example to a Gateway API implementation.

Secrets: base64 is not encryption

The Kubernetes Secret object gives a false sense of protection. The official documentation makes three points clear:

  • By default, secrets are stored unencrypted in etcd, the API server's data store. Anyone with access to etcd or one of its backups can read them.
  • Base64 encoding provides no confidentiality. It only obscures them so they cannot be read at a glance.
  • Anyone who can create a pod in a namespace can read every secret in that namespace, even without direct permission on them: mounting them in a pod they control is enough.

What to review:

AspectWhat to check
Encryption at restOn self-managed clusters, that the API server starts with an encryption configuration (EncryptionConfiguration), ideally with a KMS provider; on managed services, what encryption the provider applies and whether you can use your own key
Access to secretsWho has get, list or watch on secrets and who can create pods in each namespace
Secrets outside the clusterPlain-text values in manifests, Helm values files, Git repositories or container images
Environment variablesSecrets injected as variables, which end up in crash dumps and diagnostic tools
External managerWhether a cloud or third-party secrets manager with rotation is used instead of copying values into the cluster

In practice, the most exposed secrets are not in etcd but in the deployment repository: a values file with the database password, committed to Git two years ago and never rotated.

Managed Kubernetes: EKS, AKS and GKE

On a managed service, the provider takes care of the control plane: the API server, etcd and their availability. Everything else is still yours: node configuration, RBAC, workloads, network policies, secrets and, above all, the bridge between Kubernetes identities and cloud identities.

That bridge is the most exploited point. A node has a cloud role or identity to do its job; if a pod can reach the node's metadata service, it can obtain those credentials. The EKS best practices guide warns about this explicitly and recommends requiring IMDSv2 with a hop limit of 1 so pods cannot reach it. Watch the defaults: in managed node groups the limit is 2, which lets pods through; EKS Auto Mode, by contrast, enforces a limit of 1.

The right alternative is to give each application its own cloud identity, tied to its Kubernetes service account:

ServicePer-workload identityWhat to review
Amazon EKSIAM Roles for Service Accounts (IRSA) or EKS Pod IdentityPod access to the node's metadata service and the permissions of each associated role
Azure AKSMicrosoft Entra Workload IDThat no configuration remains from the old pod-managed identity, now retired
Google GKEWorkload Identity Federation for GKEThat the GKE metadata server is enabled, so pods cannot reach the Compute Engine one

Two other EKS details that come up often in reviews: control plane logs, including the audit log, are not sent to CloudWatch by default, and the API server endpoint is public by default, protected by IAM and RBAC. Neither is a flaw in itself, but both should be conscious decisions.

Monitoring, versions and images

Three areas nobody notices until they are needed:

  • Audit logging. On a self-managed cluster, if the API server does not start with an audit policy (--audit-policy-file), no events are logged. On managed services it has to be enabled and sent somewhere someone reviews it. Without it, there is no way of knowing what an attacker did with a stolen token.
  • Versions. The project maintains the three most recent minor versions, each for roughly 14 months. An out-of-support cluster stops receiving security patches, and the same goes for its add-ons: ingress controllers, CNIs, operators and Helm charts installed years ago.
  • Images. Most known vulnerabilities in a cluster are not in Kubernetes but in the images it runs. The sensible approach is minimal base images, scanning in the pipeline and in the registry, pinning by digest rather than by tag, and an admission policy limiting which registries can be deployed from.

The security of the pipeline that builds and deploys those images is a topic of its own: if an attacker controls the CI/CD, they control what runs in the cluster. We cover it in the resource on CI/CD pipeline pentesting.

How a Kubernetes cluster is audited

A complete audit combines two perspectives: configuration against a baseline and behaviour against an attacker.

TestQuestion it answersHow it is done
CIS baselineDo the control plane, nodes and policies follow the recommendations?CIS Kubernetes Benchmark (and its EKS, AKS and GKE variants) with kube-bench
Cluster postureWhich workloads break good practice?Scanners such as Kubescape (a CNCF incubating project) or Trivy, which also scans images
RBAC analysisWho can do what, and who can escalate?Review of roles and bindings, kubectl auth can-i per identity, permission graph tools
External surfaceWhat is visible from the internet?Discovery of API servers, dashboards, kubelet ports, ingress and LoadBalancer or NodePort services
Compromised podHow far does an attacker get with a shell in an application?From a test pod: service account token, internal network, cloud metadata, node escape, secrets
Bridge to the cloudWhat does whoever controls a pod or a node get in the cloud account?Effective permissions of node roles and per-workload identities

The first two rows automate well and should run continuously. The last four are the ones that find the paths that end in an incident, because they depend on combining findings: an application with a flaw, a service account with too many permissions, a pod that reaches the metadata service and a node role that can read every bucket.

A word on tools: kube-hunter, widely cited in older guides, is no longer actively developed and its own repository recommends Trivy. And no tool replaces testing from a compromised pod, which is the one that answers the question that matters.

FAQ

Is Kubernetes insecure by default?

Not exactly, but its defaults favour functionality: pods are not network-isolated, secrets are stored unencrypted in etcd and audit logging does not switch itself on. A freshly created cluster is fine to start working with, not for production with sensitive data until it is hardened.

Are Kubernetes Secrets encrypted?

Not by default: they are stored unencrypted in etcd and base64 encoding provides no confidentiality. You need to enable encryption at rest on the API server or check what the managed service offers, limit who can read them or create pods and, preferably, use an external secrets manager with rotation.

What replaces PodSecurityPolicy?

Pod Security Admission, which applies the Pod Security Standards (Privileged, Baseline and Restricted) through labels on each namespace and has been stable since Kubernetes 1.25, the same version in which PodSecurityPolicy was removed. For more specific rules it is complemented by policy engines such as Kyverno or OPA Gatekeeper.

If we use EKS, AKS or GKE, is cluster security the provider's job?

Only the control plane's. RBAC, pod configuration, network policies, secrets, images and the relationship between Kubernetes and cloud identities remain your responsibility, and that is where most incidents happen.

Is running kube-bench or a posture scanner enough?

It is a good starting point and should run continuously, but it is not enough. Those tools compare configuration against rules; they do not check what an attacker can do by chaining a vulnerable application, an over-privileged service account and access to the node's cloud role. That needs offensive testing from a compromised pod.

We still use ingress-nginx: what should we do?

Plan the migration as soon as possible. The project was retired in March 2026 and no longer receives security patches, after a critical 2025 vulnerability that allowed taking over the cluster from the pod network. The alternative the project recommends is Gateway API, through one of its implementations, or another maintained ingress controller.

Related service

cloud penetration testing, including EKS, AKS and GKE clusters

Related content

Sources

Audit the security of my Kubernetes cluster