Least-privilege access for AI agents on Kubernetes usually fails quietly, and the same way every time: someone grants a wildcard to ship a feature, the agent works, and the over-grant never gets walked back. By the time anyone looks, an agent that was supposed to restart pods can read every secret in the cluster. Start with the mistakes, because the correct model is mostly what you get from refusing to make them.
The RBAC mistakes that bite first
- Wildcards in the Role. A rule with
verbs: ["*"]orresources: ["*"]is least-privilege in name only. It is the single most common over-grant, and it is invisible until an incident reads it back to you. - ClusterRoleBinding where a RoleBinding would do. Binding an agent at the cluster scope when it only needs one namespace hands it the whole cluster. The blast radius is now everything, not one workload.
- Standing access with no expiry. RBAC grants do not time out. A scope the agent needed once on Tuesday is still live next quarter, sitting there as resting privilege the agent never gives back.
- Reusing a human's permissions. Pointing the agent at an engineer's group bindings means the agent inherits everything that person can do, which is almost never the least the task needs.
- No record of what was actually used. Without a session-level record of which verbs and resources the agent touched, you cannot tighten the grant later, so it only ever grows.
Every one of these has the same root. The privilege is defined once, statically, and then never reconciled against what the task actually requires this minute.
What least-privilege has to mean for an agent
Turn the mistakes around and the model appears. Least-privilege access for an agent means the grant carries the narrowest set of verbs and resources the task needs, scoped to a namespace rather than the cluster, ending on its own rather than persisting, tied to the agent's own identity rather than a human's, and recorded so it can be tightened. Static RBAC can express the first two. It struggles badly with the last three, because RBAC has no native notion of "for this task, for the next ten minutes."
The model that holds the line
The architectural requirement is that the privilege boundary sits where the agent cannot widen it. If the agent can edit its own RBAC, or mint its own access, least-privilege is a suggestion. The boundary has to be enforced by something outside the agent process. That is what hoop.dev is built to do. The agent reaches the Kubernetes API through hoop.dev, a Layer 7 access gateway and identity-aware proxy in front of the cluster's access path. Access is brokered per task against the agent's identity, the scope is enforced at the gateway where the agent cannot reconfigure it, and each session is recorded outside the agent. Least-privilege stops being a static RBAC object you hope nobody widened and becomes a property of the access path. The learn pages on per-task access explain the model, and the getting-started docs for fronting a Kubernetes cluster cover the connection.
