Disable Kubernetes service account token automount
# On the pod (or its ServiceAccount): don't mount a token unless neededapiVersion: v1kind: Podspec: automountServiceAccountToken: false # ...# Or default it off for a whole ServiceAccount:apiVersion: v1kind: ServiceAccountmetadata: name: default namespace: ordersautomountServiceAccountToken: falseWhy it matters
Section titled “Why it matters”By default, every pod gets a service account token mounted into it at
/var/run/secrets/kubernetes.io/serviceaccount/token. That token authenticates to
the API server. Most application pods never use it — they talk to a database and
serve HTTP, not the Kubernetes API — but it’s mounted anyway.
That mounted token is a credential sitting inside your workload. If the pod is
compromised — an RCE in your app, a malicious dependency, an SSRF that reaches the
filesystem — the attacker reads the token and can now query the API server as that
service account. What they can do next depends entirely on
what the service account’s RBAC grants, and if
it’s the default service account with more than it should have, that’s a foothold
into the cluster from a single compromised container.
Turning off automount removes the credential from pods that don’t need it. There’s nothing for the attacker to steal, and the pod loses no functionality it was actually using.
The default service account is the specific trap
Section titled “The default service account is the specific trap”Every namespace has a default service account, and every pod that doesn’t
specify one uses it. So the default SA is mounted into a lot of pods — which
means:
- Don’t grant the
defaultservice account any permissions. Anything you give it is given to every pod in the namespace that didn’t ask for a specific identity. Keep it empty, and give workloads that need API access their own named service account. - Set
automountServiceAccountToken: falseon thedefaultSA in every namespace, so the common case — a pod that never named a service account — gets no token at all.
A workload that genuinely needs API access then opts in: its own service account, its own scoped role, and automount left on for that one.
Where to set it
Section titled “Where to set it”The setting can go in two places, and the pod spec wins:
- On the ServiceAccount — the default for pods using it.
- On the Pod — overrides the service account’s setting for that pod.
The robust pattern is off-by-default on the service account, on-by-exception on the specific pods that call the API. That’s the same opt-in-to-privilege shape as the rest of this cluster.
Related
Section titled “Related”- RBAC least privilege — what a stolen token can do depends on this.
- Restrict privileged containers — reducing how a pod gets compromised in the first place.