Static Permission Scoping Fails for AI Agents
Most writing about agent access control, including ours, assumes permissions are assigned once and hold. You scope the agent, apply least privilege, give it a non-human identity, and authenticate it. The grant is set at deployment and it stays put.
That model assumes the agent needs the same access on every invocation. Agents don't work that way. The same agent legitimately requires different access on different calls, and that is the normal case, not an edge case. When permissions are fixed at deployment but the right level of access is determined per request, the fixed grant is wrong almost every time it is used.
The confused deputy, restated for agents
An agent is a textbook confused deputy. It holds standing privileges and acts on behalf of callers who have fewer. The moment one agent serves more than one user, its static grant has to be the union of everything any of those users might legitimately need. That union is over-privilege by construction. It is the maximum any caller could require, applied to every caller, including the ones who should have almost nothing.
Take a support agent serving both EU and US customers, both self-serve and enterprise accounts. Scope it for the broadest case and it is over-privileged for the narrowest, a self-serve user's request runs with access sized for an enterprise admin. Scope it for the narrowest and it fails at its job, unable to serve the enterprise cases it was built for. There is no static grant that is right, because the requests it serves do not share a permission profile.
This is not the agent misbehaving. It is a direct consequence of how the agent is deployed: one identity, one grant, many callers with different entitlements.
Why this is worse for agents than for traditional services
Service accounts have always carried standing privileges too. The confused deputy is an old problem. Four things make it sharper for agents.
The caller changes. A service account maps to a workload, and that workload is the same on every call. An agent maps to a workload acting for a human, and the human is different each request, with their own entitlements that vary from one invocation to the next. The identity that matters for the access decision is not the agent's. It is the caller's, and it is not stable.
Data classification is not known in advance. An agent does not know it is about to touch PII until a retrieval returns it. The sensitivity of what it handles is determined mid-execution, after the permission decision has already been made under static scoping. You cannot scope for data you have not seen yet, and the agent routinely does not see it until the call is underway.
Delegation breaks the chain. When one agent invokes another, whose context governs the second agent's access? The calling agent's, or the original human's? Static grants have no answer. Each agent carries its own standing privileges, and the second agent acts with its grant rather than the caller's. This is how privilege quietly escalates across a multi-agent system: every hop resolves to the invoked agent's scope, and the original caller's limits are lost after the first delegation.
Jurisdiction is request-level. The same agent may serve a request that must stay inside the EU and one that carries no such constraint, minutes apart. Jurisdiction is a property of the request, the caller, and the data, not of the deployment. A grant fixed at deployment cannot express a rule that changes per call.
What decision-time resolution actually means
If a static grant cannot be right, the entitlement has to be resolved when the request arrives, from the context of that request. That resolution draws on four attribute classes.
Invoking identity. Who triggered this call, and what are they entitled to? The agent must never exceed the caller. If the human who invoked it cannot read a record, the agent acting for them cannot either, regardless of what the agent's own identity permits.
Workload context. Which application, environment, and deployment is this running in? Production and staging should not resolve to the same access. An agent running in a test environment should not reach production data because its identity happened to carry the grant.
Data classification. What is the agent about to touch on this specific call, and does the caller have rights to it? This is the attribute that static scoping cannot capture, because it is only known once the data is in hand.
Jurisdiction. Where is the data, where is the caller, and which regime applies to this request right now? An EU resident's data under an EU request resolves differently from the same agent serving a US request seconds later.
These compose. The decision is a function of all four, not a lookup against one. An agent can hold the right invoking identity and still be denied because the data classification or the jurisdiction rules it out on this call. Resolving one attribute and ignoring the rest reproduces the static problem with more steps.
The hard part: where the attributes come from
Decision-time resolution is only as trustworthy as the source of its attributes, and this is where most designs quietly fail.
If the agent supplies its own context, an attacker who can influence the agent's reasoning can influence its permissions. A prompt-injected agent that self-reports its caller as an administrator has just escalated privilege through text. The permission decision was sound, it resolved from the attributes it was given, but the attributes were the agent's assertions about itself, and those assertions were attacker-controlled.
Attributes must come from trusted infrastructure. The invoking identity comes from the identity provider, not from the agent's claim about who called it. The workload context comes from the workload identity, not from a string the agent constructs. The data classification comes from the data layer's own labeling, not from the agent's description of what it retrieved. The jurisdiction comes from the request's verified origin and the data's known residency, not from the agent's inference.
The agent's own statements about itself are never an authoritative input to its own access decision. State this as a hard rule and design to it. It is the single constraint that separates decision-time resolution that improves security from decision-time resolution that hands the attacker a new lever.
Be honest about the tradeoffs
Decision-time resolution is not free, and pretending it is sets up the reader to be surprised later.
It costs latency on every call. Resolving four attribute classes from authoritative sources adds a policy lookup to the hot path of every request, and that cost is paid every time, not once at deployment.
It requires attribute sources to be available and current. The identity provider, the workload identity service, the data classification layer all have to be reachable and accurate at decision time. That is real infrastructure work, and the quality of every access decision depends on it.
And it forces an uncomfortable question: what happens when the policy decision point is unreachable? Fail open and a resolution outage becomes an access-control outage, the agent runs with whatever it can, which is the over-privilege you were trying to escape. Fail closed and a resolution outage becomes a service outage, the agent denies requests it should have served. There is no default answer. Decide it deliberately, in design, with the failure mode you can tolerate in front of you, rather than discovering your choice during an incident.
What to instrument
- A defined set of attributes per agent. Know which attribute classes govern each agent's access, rather than assuming a single scope covers it.
- An authoritative source for each attribute. Every attribute maps to a trusted infrastructure source, and none of them resolve from the agent's own assertions.
- A hard rule that an agent can never exceed its invoking caller. The caller's entitlements are the ceiling, enforced at resolution, not left to the agent's standing grant.
- Explicit handling of context propagation across delegation. When one agent calls another, define whose context governs and carry it through, so privilege does not reset to the invoked agent's scope at each hop.
- Logging of the resolved decision alongside the action. Record which attributes were used, what they resolved to, and why access was granted, so an auditor can reconstruct the decision at that moment rather than infer it from a static grant that no longer reflects what happened.
An agent that resolves its entitlements at decision time, from attributes it cannot forge, is one you can reason about per request instead of hoping a single grant was sized correctly for every request it will ever serve. That is the difference between an inventory of standing privileges and an access model that reflects what the agent is actually doing, for whom, on which data, under which regime, right now.
See how Arthur helps teams discover, secure, and govern agents across their environment. Book a demo or explore the Agent Development Toolkit to get started.