Default configurations in Kubernetes treat every workload as if it might eventually need to talk to the API server, dropping standard JWT bearer tokens into containers that never requested them. When an application vulnerability allows an attacker to execute commands inside a pod, these mounted service account tokens provide an immediate identity context. If that identity carries over-broad Role-Based Access Control (RBAC) permissions, what began as a localized web application compromise quickly escalates into full cluster takeover.
Understanding this attack path requires looking beyond standard vulnerability scanners and examining how default identity propagation interacts with permissive authorization policies.
The Default Token Mount Trap
Unless explicitly instructed otherwise, the Kubernetes kubelet automatically mounts a ServiceAccount’s API token into every container at /var/run/secrets/kubernetes.io/serviceaccount/token. Along with the token, the kubelet injects the cluster CA certificate (ca.crt) and a file containing the current namespace name.
For the vast majority of microservices—such as stateless web frontends, backend APIs, or databases—access to the Kubernetes API server is completely unnecessary. However, because the token exists on the local filesystem, any arbitrary code execution or local file inclusion (LFI) vulnerability exposes these credentials immediately.
An adversary operating inside a compromised container can read this token file and present it directly to the internal API server endpoint, typically reachable via the environment variable KUBERNETES_SERVICE_HOST or the internal DNS name kubernetes.default.svc.
# Inspecting the mounted identity token inside a running pod
cat /var/run/secrets/kubernetes.io/serviceaccount/token
If the token belongs to the default ServiceAccount in a namespace where custom RBAC policies haven’t been tuned, or if a developer bound a high-privilege ClusterRole to a standard workload, the API server will authenticate the request and evaluate the permission set.
Mapping Token Privileges with Native Tooling
Once a token is extracted, an attacker does not need external tools to discover what operations they are permitted to perform. The Kubernetes API exposes a self-subject evaluation endpoint designed specifically for querying one’s own effective permissions.
Using kubectl from outside the cluster—or raw curl commands using the extracted JWT—an operator can enumerate allowed verbs and resources across namespaces.
# Querying API permissions using an extracted token
kubectl auth can-i --list --token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) \
--server=https://<API_SERVER_IP>:6443 \
--certificate-authority=/path/to/ca.crt
Common configuration errors that enable rapid escalation include:
- Binding
ClusterRole/cluster-adminto a workload service account instead of a user or deployment controller. - Granting
createorpatchpermissions onpodsordeployments, allowing an attacker to launch new malicious pods or alter existing specs to mount host paths or administrative tokens. - Granting
getorlistaccess tosecretsacross all namespaces, allowing plaintext extraction of sensitive API keys, cloud provider credentials, or TLS private keys. - Granting
impersonateverbs on users or service accounts.
If the returned capability matrix shows permission to create pods or read secrets, the boundary between the container context and cluster management has effectively dissolved.
Hardening Workloads: Disabling Automatic Token Mounts
The most direct fix for unnecessary token exposure is stopping the kubelet from mounting tokens where they are not required. This control can be applied globally at the ServiceAccount level or overridden for individual Pod specs.
To disable automatic token mounting across all workloads using a specific ServiceAccount, set automountServiceAccountToken: false in the account definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: application-sa
namespace: production
automountServiceAccountToken: false
If a shared ServiceAccount must retain token mounting for specific workloads, enforce the control directly within the Pod manifest:
apiVersion: v1
kind: Pod
metadata:
name: payment-service
namespace: production
spec:
automountServiceAccountToken: false
serviceAccountName: application-sa
containers:
- name: api
image: payment-api:v2.1.0
ports:
- containerPort: 8080
When automountServiceAccountToken is set to false, the directory /var/run/secrets/kubernetes.io/serviceaccount/ is never created inside the container, eliminating the credential file from disk entirely.
Structuring Least-Privilege RBAC Policies
When a workload legitimately requires API access—such as an ingress controller, monitoring agent, or custom operator—its permissions must be strictly scoped using explicit Role definitions rather than permissive ClusterRole bindings.
Avoid wildcard definitions in verbs or resources. Instead, grant only the specific operations required on the exact resources utilized by the application.
# A properly scoped, namespace-bounded Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: pod-status-viewer
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: bind-pod-status-viewer
namespace: production
subjects:
- kind: ServiceAccount
name: monitoring-sa
namespace: production
roleRef:
kind: Role
name: pod-status-viewer
apiGroup: rbac.authorization.k8s.io
Key rules for maintaining secure RBAC configurations:
- Use
RoleandRoleBindinginstead ofClusterRoleandClusterRoleBindingwhenever access can be restricted to a single namespace. - Never grant
asterisk (*)wildcards inverbs,apiGroups, orresourcesin production configurations. - Audit existing bindings periodically using automated tools like
kube-rbac-auditor nativekubectl get clusterrolebindings -o yamlqueries to flag accounts bound to standard administrative roles. - Separate deployment identities from execution identities; the account running a pod should never hold permission to modify its own deployment manifest or sibling pods.
Related content
Hardening Kubernetes RBAC: Auditing and Downsizing ClusterRoles Safely
ResearchThe IAM Blind Spots That Keep Showing Up in Cloud Assessments
ResearchDemystifying Container Escapes: Mechanics of Privilege and How to Block Them
ResearchS3 Leaks Beyond ACLs: Audit Resource Policies and Access Points
Want a second set of eyes on your security posture?
Let's talk about where your real exposure is.
Book an advisory call