Every pod in your cluster is handed a token that authenticates it to the Kubernetes API, whether the application inside it ever calls the API or not. It is mounted by default, it does not expire unless you configure it to, and if the pod is compromised, so is whatever that token permits.
Most applications never use it. It sits there anyway, because the default is on.
This post is what the default token is, what it grants, and how to turn it off for the pods that do not need it. For whoever runs workloads on Kubernetes.
What gets mounted, by default
Every pod, unless told otherwise, gets a projected volume containing a token, a certificate authority bundle, and the namespace name, at a fixed path any process in the container can read.
The token authenticates as the pod's service account. If that account has no role bindings, the token can do very little. If it has the default permissions many clusters ship with, or permissions added for one specific job and never scoped down, it can do considerably more: list secrets in the namespace, read config maps, list or delete pods, sometimes act across namespaces.
The part that matters: the token is present whether or not the application uses it. A web server that never calls the Kubernetes API still carries a live credential to that API, readable by anything that can read a file in the container.
Why this is worse than it looks
A container compromise becomes a cluster compromise. An attacker with code execution in a pod does not need to escape the container. They read the token from the filesystem and call the API directly, with whatever the service account permits, from anywhere they have network access to the API server.
Permissions accumulate. A role gets list secrets because one feature needed it once, and it stays granted to every pod using that service account afterwards, including ones added later for unrelated reasons.
The default service account is shared. Every pod in a namespace that does not specify one uses default, so a permission granted to it, even by accident, reaches everything in that namespace.
It is easy to forget it exists. Unlike an API key you provisioned deliberately, this credential appears without anyone asking for it, so it is absent from inventories that only list things somebody remembers creating.
Turn it off where it is not needed
Most workloads never call the Kubernetes API and should not have the token at all:
apiVersion: v1
kind: Pod
spec:
automountServiceAccountToken: false
Or at the service account level, which covers every pod using it:
apiVersion: v1
kind: ServiceAccount
automountServiceAccountToken: false
This removes the credential entirely for anything that does not need to talk to the control plane, which is most of a typical cluster. Audit your service accounts and set this as the default, opting specific workloads back in rather than the reverse.
For workloads that do need it
A dedicated service account per workload, never the shared default. Scoping is meaningless if every application shares one identity.
RBAC scoped to the specific verbs and resources needed, in the specific namespace, never cluster-wide unless the workload is genuinely cluster-scoped. get and watch on one config map is a different exposure from list and delete on all secrets.
Bound, short-lived tokens rather than the legacy long-lived kind. Modern Kubernetes issues time-bound, audience-scoped tokens by default, which expire and can be tied to a specific consumer rather than working anywhere the API is reachable. Confirm you are actually using this rather than a mounted secret-based token carried over from an older cluster.
No wildcard verbs or resources, ever, in role definitions. A wildcard in an RBAC rule is the cluster equivalent of the database user that can do everything.
Check yours
# Does the default service account in each namespace have any bindings?
kubectl get clusterrolebinding,rolebinding --all-namespaces \
-o jsonpath='{range .items[*]}{.subjects[?(@.name=="default")]}{.metadata.namespace}{"\n"}{end}'
# Which pods have the token mounted, and do they use the API?
kubectl get pods --all-namespaces -o json | \
jq -r '.items[] | select(.spec.automountServiceAccountToken != false) | "\(.metadata.namespace)/\(.metadata.name)"'
# From inside a running pod, is the token there and what can it do?
kubectl exec <pod> -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
kubectl auth can-i --list --as=system:serviceaccount:<namespace>:<sa>
That last command is the one that answers the real question: not whether a token exists, but what it is actually allowed to do. Run it for every service account bound to anything beyond the basics, and the results are usually broader than whoever configured the role remembers granting.
The concession
Disabling the automount for every pod and re-enabling it deliberately is more configuration than most teams apply today, and for a cluster where every service account already has minimal, reviewed permissions, the marginal benefit is smaller. Some tooling and sidecars expect the token to be present and break in ways that are annoying to debug when it is missing.
The proportionate order: default it off for new workloads going forward, audit which existing service accounts have any binding beyond nothing, and fix those first. A cluster where most tokens grant nothing is most of the way there even with the setting left at its default in the manifests you have not touched yet.
The implication
The Kubernetes token is a credential you did not ask for, mounted in every pod, and its value depends entirely on a role binding somebody made months ago for a reason nobody remembers.
Run the auth can-i --list command against your most exposed workload. Whatever it can do is what an attacker gets the moment that pod is compromised, whether or not the application was ever meant to touch the API.