Join our Newsletter — 33% off our NHI Course
Home› Guides› How to find pods that automount service account…
Guide Cloud & Workload Identity

How to find pods that automount service account tokens: Inventory, triage and switch off unneeded token mounts

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 11 November 2026 13 min read
On this page

Every Kubernetes Pod gets an API token for its service account unless someone explicitly turns it off, so most clusters run hundreds of workloads holding credentials they never use. If an attacker gets code execution in one of those containers, the token at /var/run/secrets/kubernetes.io/serviceaccount/token lets them call the API server as that service account. This runbook shows how to find which Pods actually have the token mounted, separate the ones that need it from the ones that do not, switch the mount off safely and stop new Pods from getting it by default. It is for platform engineers and cluster administrators on self-managed or managed Kubernetes. For background on how these tokens work, see the Kubernetes Service Account Token Guide.

This is an independent guide from NHI Mgmt Group, based on the Kubernetes project's public documentation as of November 2026. Behaviour can change between Kubernetes releases, so confirm against the documentation for your version.

Key takeaways

  • Mounting is the default. The ServiceAccount admission controller adds a projected volume named kube-api-access-<suffix> to every new Pod unless the ServiceAccount or the Pod sets automountServiceAccountToken: false.
  • The Pod setting wins. When both the ServiceAccount and the Pod spec set the field, the Pod spec takes precedence, so check both and trust the Pod's volumes as the final answer.
  • Look at volumes, not just flags. The reliable test is whether the running Pod has a projected volume with a serviceAccountToken source; the flags only explain why.
  • Most workloads never call the API server. Use audit logs and RBAC lookups to prove which service accounts are used, then disable the mount for the rest.
  • Changes only affect new Pods. Admission runs when a Pod is created, so you must restart workloads, and you can roll back by restoring the field and restarting again.

When you need this

  • Cluster hardening: the Kubernetes RBAC good practices page advises avoiding the default automounting of service account tokens by setting automountServiceAccountToken: false.
  • After a container compromise or vulnerable image report: any Pod with a mounted token gives an attacker an authenticated starting point. MITRE ATT&CK tracks this as T1528 Steal Application Access Token and T1552.007 Container API. The Kubeflow cryptomining attacks show how a mounted service account turns one exposed workload into control of the cluster.
  • Before tightening RBAC: knowing which Pods hold tokens tells you where an over-broad RoleBinding is reachable from inside a container.
  • Audit evidence: least privilege controls such as NIST SP 800-53 AC-6 expect you to show that credentials are issued only where needed.

Before you start

Understand what the token mount is before you go looking for it. According to the Kubernetes documentation, when neither field is false the admission controller adds a projected volume with three sources and mounts it into each container at /var/run/secrets/kubernetes.io/serviceaccount, skipping containers that already mount that path.

File in the mountSource in the projected volumeWhat it gives the container
tokenserviceAccountToken, expirationSeconds: 3607A JWT bound to the Pod, audience the API server, renewed by the kubelet; it expires when the Pod is deleted or after its lifespan (one hour by default)
ca.crtConfigMap kube-root-ca.crtThe cluster CA bundle, so the client can verify the API server
namespaceDownward API metadata.namespaceThe Pod's namespace name

The token is short-lived, but the kubelet keeps refreshing it for as long as the Pod runs, so an attacker inside the container always has a valid one. Kubernetes versions before 1.22 mounted a long-lived token from a Secret instead; legacy Secrets of type kubernetes.io/service-account-token may still exist and are covered in How to rotate a Kubernetes service account token and detect old token use.

You need:

  • Read access: get and list on Pods, ServiceAccounts, RoleBindings and ClusterRoleBindings across namespaces. Run discovery from a read-only identity, not cluster-admin.
  • Tools: kubectl and jq. The jq filters below read documented Pod fields; adjust them to your shell.
  • Audit logs: API server audit logging at Metadata level or above, retained for at least 30 days, so you can see which service accounts call the API. Managed services expose these through their logging service. See the Kubernetes Audit Log Detection Guide.
  • An owner list: who owns each namespace, so you can confirm before you change anything.

Step-by-step

Steps 1 to 5 are read-only. Steps 6 and 7 change configuration and are reversible by restoring the field and restarting Pods.

  1. List running Pods that actually have a service account token volume. This is the ground truth, because it reflects what admission did when each Pod was created:
    kubectl get pods -A -o json | jq -r '
      .items[]
      | select([.spec.volumes[]?.projected.sources[]?.serviceAccountToken] | map(select(. != null)) | length > 0)
      | [.metadata.namespace, .metadata.name, (.spec.serviceAccountName // "default")]
      | @tsv'
    Volumes named kube-api-access-* are the automounted ones. Other projected volumes with a serviceAccountToken source were added on purpose, often for a non-API audience such as a cloud workload identity integration or a service mesh. Record both, but treat them separately.
  2. Find legacy Secret-based token mounts. List Secrets of the legacy type, then check whether any Pod mounts them as a volume:
    kubectl get secrets -A -o json | jq -r '
      .items[] | select(.type == "kubernetes.io/service-account-token")
      | [.metadata.namespace, .metadata.name, (.metadata.labels["kubernetes.io/legacy-token-last-used"] // "-")] | @tsv'
    The kubernetes.io/legacy-token-last-used label is written by the API server when legacy token tracking is active. These tokens do not expire, so they rank above automounted tokens in your clean-up order.
  3. Read the settings that explain the result. List the ServiceAccount and Pod values using the documented -o jsonpath range syntax:
    kubectl get serviceaccounts -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.automountServiceAccountToken}{"\n"}{end}'
    kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.serviceAccountName}{"\t"}{.spec.automountServiceAccountToken}{"\n"}{end}'
    An empty column means the field is unset, which behaves as true. Use the decision table below to classify each Pod.
  4. Find out what each service account can do. For every service account behind a mounted token, list its effective permissions by impersonating it:
    kubectl auth can-i --list --namespace <ns> --as system:serviceaccount:<ns>:<sa>
    The default ServiceAccount in each namespace has no permissions beyond the API discovery permissions granted to all authenticated principals, unless someone has bound a role to it. Any binding to a default account is a finding in its own right. Pair this with How to Audit kubernetes cluster admin bindings to rank Pods whose token reaches cluster-admin or Secret read access.
  5. Prove which tokens are used. Search your audit logs for requests whose user.username is system:serviceaccount:<ns>:<sa> over your review window. Bound tokens carry private claims such as authentication.kubernetes.io/pod-name and authentication.kubernetes.io/credential-id in the authenticated user's extra fields, which lets you tie a call to a specific Pod. A service account with a mounted token and no API calls in 30 to 90 days is a candidate for disabling. Confirm with the owner: some controllers only call the API during failover or scaling events.
  6. Disable the mount where it is not needed. Prefer the ServiceAccount level for dedicated accounts and every default account, and the Pod template level for workloads that share an account:
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: default
      namespace: <ns>
    automountServiceAccountToken: false
    For a Deployment, set spec.template.spec.automountServiceAccountToken: false in the manifest held in source control, not with a live patch, so your GitOps tooling does not revert it.
  7. Restart the workloads. Admission only acts when a Pod is created, so existing Pods keep their tokens until replaced. Roll out in rings: one non-production namespace, then low-risk production namespaces, then the rest. Use your normal deployment process or kubectl rollout restart deployment/<name> -n <ns>, and watch for errors before moving on.

Decision table

ServiceAccount fieldPod fieldToken mounted?Action
unset or trueunsetYesDefault case. Disable unless audit logs show API use
falseunsetNoTarget state for most accounts
falsetrueYesDeliberate opt-in. Confirm the workload needs it and its RBAC is narrow
unset or truefalseNoFine for that Pod, but other Pods using the account still get tokens
anyany, with an explicit projected serviceAccountToken volumeYes, customCheck the audience and path; not controlled by the automount field

Which workloads usually need the token

  • Controllers and operators: anything that watches or changes Kubernetes objects, such as ingress controllers, cert managers, autoscalers and custom operators. See the Kubernetes Operator Security guide.
  • Agents in system namespaces: CNI, CSI, logging and monitoring DaemonSets often read node or Pod metadata. Do not change accounts in kube-system or vendor-managed namespaces without the vendor's guidance.
  • CI runners and job launchers: they create Pods or Jobs, so their tokens are powerful and deserve the tightest RBAC.
  • Ordinary application Pods: web services, APIs, batch jobs and databases rarely call the Kubernetes API. These are the bulk of the clean-up.

Verify it worked

  • Re-run step 1. The changed workloads should no longer show a kube-api-access-* volume after their Pods are replaced.
  • Inspect one Pod: kubectl get pod <name> -n <ns> -o yaml should show no projected token volume and no mount at /var/run/secrets/kubernetes.io/serviceaccount.
  • Check the application: readiness probes pass, error rates are flat and logs show no authentication failures to the API server.
  • Check audit logs: a sudden burst of 401 responses for a system:serviceaccount user after the change means a workload did need its token.

Rollback and common errors

Rollback: set automountServiceAccountToken: true on the Pod template (which overrides the ServiceAccount) or remove the false value from the ServiceAccount, then restart the workload. No data is lost: the token is minted fresh for each new Pod.

SymptomLikely causeFix
Application logs show it cannot read the token file or load in-cluster configThe workload uses a Kubernetes client library and did need the tokenOpt the Pod back in with the Pod-level field, and give it a dedicated ServiceAccount with narrow RBAC
Change made but Pods still have the volumePods were not recreated, or the Pod template sets the field to trueRestart the workload; check the Pod template overrides
Field reverts after a few minutesGitOps or a Helm release reconciles the live object backMake the change in the chart values or manifests in source control
Pods still get a token volume with a different nameA webhook or chart adds its own projected serviceAccountToken volumeReview that integration separately; the automount field does not control it
Pod creation rejected after a policy rolloutAn enforcing admission policy blocks Pods that request the tokenAdd a documented exception for the workload or switch the policy to audit mode while you fix it

Hardening afterwards

  1. Make false the default for new namespaces. An admission policy can set the field on every new default ServiceAccount. The Kyverno community policy disable-automountserviceaccounttoken is one published example; a ValidatingAdmissionPolicy or Gatekeeper constraint can instead report or block Pods that mount tokens without an approved label. Start in audit mode. See the Kubernetes Admission Control Guide.
  2. Give every API-calling workload its own ServiceAccount. Shared accounts make it impossible to disable the mount for one workload without touching others, and they blur audit trails.
  3. Keep RBAC narrow for the accounts that keep tokens. The Kubernetes RBAC good practices page warns that the right to create workloads in a namespace implicitly grants the API access of any service account in it. See the Kubernetes RBAC Guide.
  4. Remove legacy token Secrets. Delete unused Secrets of type kubernetes.io/service-account-token once tracking shows no use; the controller manager's legacy token cleaner marks and deletes unused auto-generated ones after one year by default.
  5. Repeat the inventory on a schedule. Run steps 1 to 4 monthly and on every new namespace, and feed the result into your NHI inventory. See the Kubernetes NHI Security Guide.

Choosing where to set the field

WhereBest forTrade-off
ServiceAccountdefault accounts and dedicated accounts whose Pods never call the APIOne change covers every Pod using the account; a Pod can still opt back in
Pod templateShared accounts, or a single workload that differs from the restMust be repeated in every chart and manifest; easy to miss
Admission policyLarge estates with many teamsNeeds a policy engine and an exception process; enforce only after audit mode is clean

Small teams with a handful of namespaces can set the ServiceAccount field by hand and stop there. Larger organisations should combine the ServiceAccount default with an admission policy, because new namespaces and new charts appear faster than reviews.

Metrics

  • Token exposure rate: percentage of running Pods with a kube-api-access-* volume. Expect it to fall to the share of Pods that run controllers or agents.
  • Default account exposure: number of Pods running as a default ServiceAccount with a mounted token. Target zero.
  • Unused mounted tokens: service accounts with mounted tokens and no audit log activity in 90 days.
  • Privileged reach: Pods whose mounted token can read Secrets or create Pods cluster-wide.
  • Legacy token Secrets: count of kubernetes.io/service-account-token Secrets remaining.

Framework mapping

FrameworkReferenceHow this runbook supports it
NIST SP 800-53 Rev. 5AC-6 Least Privilege; IA-5 Authenticator Management; CM-6 Configuration SettingsIssue credentials only to workloads that need them; enforce a secure default
NIST CSF 2.0PR.AA-05; PR.PS-01; DE.CM-09Least privilege for workload access, configuration management, monitoring of runtime environments
CIS Controls v8.15.4 Restrict Administrator Privileges to Dedicated Administrator Accounts; 6.8 Define and Maintain Role-Based Access ControlNarrow and documented access for service accounts
ISO/IEC 27001:2022 Annex AA.5.18 Access rights; A.8.2 Privileged access rightsAccess rights provisioned and reviewed per workload
MITRE ATT&CKT1528 Steal Application Access Token; T1552.007 Container API; T1613 Container and Resource DiscoveryRemoves the token an attacker would steal and use for discovery

Practitioner checklist

  • List every running Pod with a projected serviceAccountToken volume and separate automounted from custom ones.
  • List legacy kubernetes.io/service-account-token Secrets and the Pods that mount them.
  • Record the ServiceAccount and Pod automountServiceAccountToken values and classify each Pod.
  • Check effective permissions of each mounted account with kubectl auth can-i --list.
  • Use audit logs to prove which service accounts call the API over 30 to 90 days.
  • Set the field to false on every default ServiceAccount and on unused dedicated accounts, in source control.
  • Restart workloads in rings and watch for 401 errors and failed probes.
  • Add an admission policy in audit mode, then enforce, with a documented exception route.
  • Track token exposure rate and default account exposure monthly.

Standards and references

Related NHI Mgmt Group resources: Kubernetes Service Account Token Guide · How to rotate a Kubernetes service account token and detect old token use · How to Audit kubernetes cluster admin bindings · Kubernetes Workload Identity Checklist · Rotating a Windows or Linux Service Account Password

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 11 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org