Overprivileged Kubernetes pods and service accounts: the blast radius of AI-generated configs
Par Seaworthy · 1 juillet 2026
The problem with "it deploys" as a success metric
When you ask an AI coding tool to generate a Kubernetes deployment manifest, you usually get something that works. The pod starts. The demo looks fine.
But "it deploys" is not the same as "it's safe." AI models learn from the enormous body of Kubernetes configs posted on GitHub, StackOverflow, and in documentation examples. Those examples often include elevated permissions because the authors were trying to get something running quickly, not writing production-grade security configs. The AI faithfully reproduces those patterns.
The result is that AI-generated deployments often run with automountServiceAccountToken: true (the default), broad RBAC bindings, and occasionally full cluster-admin privileges. Each of those is a door left open.
What a dangerously permissive pod looks like
Here is a typical AI-generated manifest for a simple web service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:latest
securityContext:
privileged: true
env:
- name: DB_PASSWORD
value: "supersecret"
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-app-admin
subjects:
- kind: ServiceAccount
name: my-app-sa
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
Several problems here, each worse than the last. privileged: true gives the container root-level access to the host kernel. The service account is bound to cluster-admin, which means any code running in that pod can do anything to any resource in the cluster. And the database password is in plaintext in the env block, which will appear in kubectl describe pod output for anyone with read access.
The blast radius when something goes wrong
Here is the thing about blast radius: it is not hypothetical. It is just a measure of how badly you lose when an attacker gets a foothold.
If a containerised app gets compromised through an RCE in a dependency or a supply chain attack, the attacker's next move is to query the Kubernetes API using the service account token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token. With cluster-admin, that query succeeds for everything. They can enumerate secrets, spawn new pods, and pivot freely across namespaces. The privilege escalation is instantaneous.
Running as privileged makes it worse. From a privileged container an attacker can mount host filesystems, access host network interfaces, load kernel modules, and break out of the container entirely. At that point you are not dealing with a compromised pod. You are dealing with a compromised node.
This is the blast radius: one exploited dependency or one misconfigured route, and you hand over the entire cluster.
A safer alternative
The same deployment, written with least-privilege in mind:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
automountServiceAccountToken: false
containers:
- name: my-app
image: my-app:latest
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-app-secrets
key: db-password
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-app-role
namespace: default
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-app-rolebinding
namespace: default
subjects:
- kind: ServiceAccount
name: my-app-sa
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: my-app-role
The changes are not dramatic but the difference in blast radius is real. No privilege escalation, no capabilities, a non-root user. Service account token mounting disabled at both the pod and service account level (you need both; setting it on one and not the other is a common mistake). A namespaced Role instead of a ClusterRoleBinding with cluster-admin. Secrets referenced from a Secret object rather than hardcoded.
If this pod is compromised, the attacker has a shell in a container with no capabilities, no cluster API access, and no path to escalation. That is a breach. Still bad. But it is not the end of the game.
Service accounts deserve more attention
The service account is the most overlooked part of this. Most developers, when they deploy to Kubernetes for the first time, do not think about service accounts at all. They use the default one. They let Kubernetes automount the token. The token is scoped to whatever RBAC exists on the default service account, which varies wildly by cluster setup.
If your app does not need to talk to the Kubernetes API, disable the token mount. If it does need API access, create a dedicated service account and bind it to the minimum set of verbs on the minimum set of resources it actually uses. Every privilege you don't grant is an attack surface that doesn't exist.
AI-generated configs will not do this for you. The training data does not reward security. It rewards configs that work.
The audit you probably haven't done
If your deployment configs were AI-generated, you probably have not audited them for privilege escalation paths. Most teams don't. The configs pass CI, the pods run, and everyone moves on.
Go check. Look for privileged: true, cluster-admin bindings, automountServiceAccountToken not explicitly set to false, and secrets in plain env vars. These are not edge cases in AI-generated output. They are the defaults you get when you ask a model to generate a working config without telling it to be paranoid.
Seaworthy is a static analysis tool that scans your repo for exactly these issues, including overprivileged Kubernetes configs, alongside checks across security, dependency hygiene, and configuration.
Cet article a été généré par IA et résume des sources publiquement disponibles.
Seaworthy analyse votre dépôt pour détecter les problèmes abordés dans des articles comme celui-ci.
Failles de sécurité, secrets exposés et mauvaises configurations détectés avant le déploiement. Gratuit, aucun compte requis.