Agentic Threat Modeling · 3 of 4L2offensive security
Modeling Agent Identity and Delegated Authority
When an agent acts, three identities are in the room at once. Threat modeling that tracks only one of them misses the delegation chain where agentic authority is actually abused.
Abstract
Classic threat modeling assumes a process runs as a stable principal, so it tracks one identity per element. An AI agent breaks that assumption: a single tool call carries the agent's own workload identity, the identity of the user it is acting on behalf of, and the audience the target tool expects to authorize. The confused deputy — the oldest authority bug there is — re-appears at this identity layer, and its medium is the token. This piece gives a method for modeling it: the Delegation Ledger, one row per hop in the chain of borrowed authority, recording who acts as whom, with what scope and audience, across which boundary, for how long. It shows how to derive the ledger from a request trace, how token exchange (OAuth on-behalf-of) should narrow rather than widen authority at each hop, how a token service enforces the ledger with audience-restricted short-lived tokens, and how to gate scope, audience, lifetime, and delegation depth in continuous integration. A worked example walks an over-scoped delegated token from grant to replay against a tool it was never meant to reach. The claim: delegated authority, modeled as an explicit chain, is the unit that makes agent identity risk representable.
Ask the deceptively simple question at the center of every agent security review — when this agent calls that tool, who is acting? — and the answer is never one name. The agent runs under its own workload identity. It is acting on behalf of a user who delegated some authority to it. And the tool it calls authorizes against the audience it expects. Classic threat modeling, which pins one principal to each element on a diagram, cannot hold three identities braided into one call. This piece models the braid directly: it treats delegated authority as a chain of hops, each hop a place where authority can be narrowed correctly or widened by accident, and gives you an artifact that makes every hop reviewable before an attacker walks it.
The identity question agents force
Traditional systems make identity easy to model because it is stable: a service runs as a service account, a request arrives with a user session, and the two rarely blur. You can label each element on a data-flow diagram with the principal it runs as and reason about privilege from there. The whole discipline of least privilege assumes you can name the one principal an action runs under.
An agent dissolves that assumption. When it invokes a tool, the call is made by the agent's own workload identity, but the authority being exercised was delegated by a user, and the tool decides whether to honor it based on the token's audience and scope. Three identities — the agent, the user it represents, and the trust the tool places in the caller — are present in a single action. The question 'who is acting' has three simultaneously true answers, and the security of the call depends on how they are bound together.
This is not a new bug given a new name. It is Hardy's confused deputy and Saltzer and Schroeder's least-privilege, relocated to the identity layer of a system that manufactures actions from untrusted text. What is new is that the deputy is now trivially manipulable, and the authority it holds is borrowed — which is exactly the condition under which borrowed authority gets abused.
Three identities in one call
Name the three precisely, because the controls differ for each. The agent's workload identity is the identity of the running process — the service principal or managed identity the agent authenticates as. The delegated user identity is the authority a user handed to the agent to act in their stead, typically carried as an on-behalf-of token. The tool audience is the resource's own expectation: the audience claim and scopes a token must present for the tool to accept it.
A secure call binds these correctly: the agent presents a token that proves 'this workload, acting for this user, is permitted this scope on this audience, until this expiry.' Every clause is a place the binding can be wrong. Present the workload's own broad identity where a narrowly-scoped delegated token was required, and the agent acts with more authority than the user ever granted. Present a token whose audience is not checked, and it can be replayed to a different resource. Omit the user and the call becomes ambient — authority with no principal behind it, which is the hardest kind to reason about or revoke.
The figure shows the shape: three inputs converge on one authorization decision, and the decision is only as sound as the least-carefully-bound of them.
Delegation is the attack surface
Once authority is delegated, the delegation itself becomes the thing an attacker targets, and the token is the medium. Four failures recur. Over-broad scope: the user delegates more than the task needs — full mailbox access for an agent that only sends one kind of message — so a compromised agent inherits authority far past its purpose. Missing audience restriction: a token accepted by any resource can be replayed from the tool it was meant for to a tool it was not. Long lifetime: a token that lives for hours is a token an attacker who captures it can use for hours. And unbounded delegation depth: an agent that can hand its borrowed authority to a sub-agent, which hands it onward, builds a chain no one is watching the end of.
The reason this surface is so productive for an attacker is the same reason the base agent threat exists: the agent decides what to do from content it does not control, and now that decision can spend a user's delegated authority. Indirect prompt injection that reaches an over-scoped, long-lived, audience-unrestricted token is not a nuisance — it is account takeover with the user's own credentials, laundered through a deputy the user trusts. OWASP's Excessive Agency (LLM06) is precisely this class: harm that follows from an agent holding more authority than its function requires.
Modeling this means refusing to treat 'the agent authenticates' as a single checkbox. Authentication is where the chain begins, not where the risk ends; the risk lives in every hop the delegated authority travels afterward.
- Counter over-broad scope by requesting only the scope a hop consumes and exchanging any broader token down at the token service before the call is made.
- Counter missing audience restriction by binding every token to a specific resource with a resource indicator, so it cannot be replayed to a tool it was not minted for.
- Counter long lifetime with short-lived tokens and per-call re-exchange, so a captured token expires before it is useful.
- Counter unbounded delegation depth by defaulting may-delegate to no and capping depth, so borrowed authority cannot travel past the modeled hops.
Modeling the delegation chain
The artifact is the Delegation Ledger: one row per hop in the chain of borrowed authority. Where the Agent Authority Inventory answers 'what can this capability reach,' the ledger answers the orthogonal question 'whose authority does each step spend, and how is it constrained.' A hop is any point where authority passes hands — user to agent, agent to tool, agent to sub-agent, sub-agent to tool.
Each row records the acting principal and the principal it acts as, the scope granted at that hop, the audience the resulting token is restricted to, the boundary the hop crosses, the token's lifetime, and whether the hop may delegate further. The two fields that make this more than an audit log are audience and delegate-further, because they are the preconditions for replay and for runaway delegation depth — the two failures a flat 'the agent has a token' model cannot see.
As with any such artifact, blanks are findings. A hop with no audience restriction is a finding. A scope that is broader than the next hop actually consumes is a finding. A hop marked 'may delegate further' with no depth limit is a finding. The ledger turns 'the agent uses delegated auth' from a reassuring phrase into a chain you can inspect link by link.
| Field | What it records | Example |
|---|---|---|
| Acting principal | The running identity making the hop | calendar-agent workload |
| Acts as | Whose authority the hop spends | user (on-behalf-of) |
| Scope | The exact scope this hop consumes | Mail.Send (not the bundle) |
| Audience | The resource permitted to accept the token | mail.internal (RFC 8707) |
| Boundary | The trust line the hop crosses | internal -> external |
| Lifetime | Token TTL for this hop | 120s, re-exchange per call |
| May delegate | Can this authority be handed onward? | No -> stops here |
Token discipline: scope, audience, lifetime, exchange
The ledger's rules are enforced by how tokens are minted and exchanged. The governing principle is that delegation should narrow authority at every hop, never widen it. When an agent needs to call a downstream tool on behalf of a user, it should not forward the broad token it received; it should exchange it for a new token scoped to exactly that call. OAuth 2.0 defines this precisely — the on-behalf-of / token-exchange flow (RFC 8693) exists to trade a subject's token for a downstream token with reduced scope and a specific audience.
Four disciplines fall out of the standards. Scope: request the narrowest scope the hop consumes, never the union of everything the agent might do. Audience: bind every token to the specific resource that will accept it, using resource indicators (RFC 8707) so a token minted for one tool is rejected by another. Lifetime: issue short-lived tokens, so a captured token is a brief liability rather than a standing one. And no ambient authority: the agent's own workload identity is for the agent's own resources; it must not be the fallback principal for actions the user delegated. NIST's Zero Trust Architecture (SP 800-207) is the frame — authorize each request against least privilege, never a static perimeter — and its Digital Identity Guidelines (SP 800-63) supply the assurance vocabulary for how strongly each principal is proven.
A token service that performs these exchanges is the natural enforcement point, because it can apply the ledger's policy at the moment a token is minted — the one place where scope, audience, and lifetime are all still decisions rather than facts.
A worked example: the over-scoped token
A user asks a calendar agent to book meetings, and in doing so delegates broad directory and mail scopes — more than booking needs, because the consent screen offered a bundle. Fill the ledger row for the agent-to-tool hop: acts-as the user, scope is the broad bundle, audience is unrestricted, lifetime is an hour, may-delegate is yes. Read across it and it is not a description; it is an attack path. A broad scope on an audience-unrestricted, long-lived, further-delegable token is a credential waiting to be redirected.
Now walk it. Indirect prompt injection in a meeting invite the agent reads steers it to call a different tool — the mail send API — with the token it already holds. Because the token's audience was never restricted, the mail resource accepts it. Because the scope was the broad bundle, it includes send. Because the lifetime is generous, timing is easy. The user's own delegated authority has been spent on an action they never authorized, by a deputy they trusted. That is the confused deputy at the identity layer, and the ledger row predicted every step of it.
The mitigation is located precisely because the row named the failures. Each countermeasure closes one filled field, and together they turn the row from an exploit into a dead end.
- Exchange the broad token for a narrowly-scoped one at the token service, so the agent-to-tool hop carries only the scope that hop consumes — not the consented bundle.
- Bind every minted token to a specific audience with resource indicators, so a token for the calendar resource is rejected by the mail resource.
- Issue short-lived tokens and require re-exchange per downstream call, so a captured or redirected token expires before it is useful.
- Set may-delegate to no and cap delegation depth, so the borrowed authority cannot be handed onward to a tool or sub-agent outside the modeled chain.
Gating delegation in continuous integration
A ledger that is not enforced is a diagram of good intentions. Make it a build-time artifact: any change that widens a scope, adds a downstream tool, enables further delegation, or lengthens a token's lifetime must update a row, and a row that fails a bound fails the build. The bounds are concrete and checkable without touching a live system — they are assertions over the ledger and the token configuration.
Four gates cover most of the surface. Assert that every hop's requested scope is a subset of what the next hop consumes, so over-broad delegation is caught statically. Assert that every minted token declares a specific audience, so audience-unrestricted tokens never ship. Assert a maximum token lifetime per boundary class, tighter for external hops. And assert a delegation-depth limit, so no chain can grow past the modeled hops. Because an agent's reachable delegation changes whenever its tools, prompts, or consented scopes change, the ledger is regenerated on those events and the gates run on every change — the same cadence as the tests beside them.
Ownership closes it, because delegation risk almost always lives in a seam. The identity team owns the token service, the agent team owns the consent request, and the tool team owns the audience check — and the dangerous combination is one none of them owns alone. NIST's AI Risk Management Framework frames exactly this: map risk to accountable roles and govern it there. The gate makes that governance executable.
- Assert each hop's scope is a subset of the next hop's consumption; block over-broad delegation.
- Assert every minted token carries a specific audience (resource indicator); block audience-unrestricted tokens.
- Assert a maximum lifetime per boundary class; block long-lived tokens on external hops.
- Assert a delegation-depth limit and require an owner on every hop; an unowned or unbounded hop is a finding.
What this catches that per-element modeling cannot
Per-element modeling labels each box with the principal it runs as and checks that principal's privilege. It is blind to the delegation chain because the risk is not in any single box's privilege — it is in how authority is bound and rebound as it crosses between boxes. The over-scoped-token attack fires no per-element threat: every component ran as exactly the principal its diagram said it would. The ledger asks the question the diagram cannot — whose authority does this hop spend, and how far can it travel — and the replay path is visible at the first hop.
It composes with what already works. The token service, the consent flow, and the resource servers are ordinary components with ordinary threats, and classic threat modeling handles them well; model them that way. The Delegation Ledger is the addition at the layer where borrowed authority moves between principals — the layer per-element modeling flattens into a single label. A mature agent identity model runs both and is explicit about the boundary between them.
The claim is not that delegated authority is now safe. Tokens leak, consent screens over-ask, and standards are unevenly implemented. The claim is that with the delegation chain as the unit, agent identity risk becomes representable — you can write down each hop, bound its scope, audience, and lifetime, cap its depth, assign it an owner, and gate the whole chain — which is the precondition for defending authority you have chosen to lend.
Key takeaways
- Every agent tool call carries three identities — the agent's workload identity, the delegated user, and the tool's expected audience; a secure call binds all three correctly.
- The confused deputy re-appears at the identity layer, and its medium is the token: over-broad scope, missing audience restriction, long lifetime, and unbounded delegation depth are the four failures.
- The Delegation Ledger is the artifact — one row per hop recording acts-as principal, scope, audience, boundary, lifetime, and whether the hop may delegate further.
- Delegation must narrow authority at every hop: exchange broad tokens for narrowly-scoped, audience-restricted, short-lived ones (OAuth on-behalf-of / RFC 8693, resource indicators / RFC 8707).
- A filled ledger row is a pre-computed replay path: broad scope plus no audience restriction plus long lifetime is account takeover with the user's own credential.
- Gate scope-subset, audience presence, lifetime, and delegation depth in CI; own every hop; keep classic threat modeling for the token service and resource servers.
Practitioner Toolkit
Copy-paste, strictly defensive artifacts you can use today. Nothing here attacks a real system.
Complete every field per hop in the chain of borrowed authority; a blank is a finding.
- Acting principal and acts-as: the running identity and the principal whose authority it spends at this hop.
- Scope: the exact scope this hop consumes — not the consented bundle, not the union of the agent's abilities.
- Audience: the specific resource permitted to accept the token (resource indicator), never unrestricted.
- Boundary: internal / external / tenant line this hop crosses.
- Lifetime: the token TTL, tighter for external hops.
- May delegate further: yes/no; if yes, the depth limit and the owner accountable for the chain's end.
The smallest version that still enforces, if you only have an afternoon.
- Trace one real request end to end and list every hop where authority changes hands.
- For each hop, record acts-as, scope, and audience; mark any hop with an unrestricted audience.
- Route minting through one token service that exchanges broad tokens for narrow, audience-bound ones.
- Cap token lifetime and set delegation depth to zero unless a hop demonstrably needs it.
The hop the token service enforces — narrow, audience-bound, short-lived, deny-by-default.
# illustrative, not runnable
hop: agent -> mail_tool
acts_as: user # on-behalf-of, not the agent's own identity
grant_type: urn:ietf:params:oauth:grant-type:token-exchange # RFC 8693
scope: [Mail.Send] # narrowest the hop consumes, NOT the bundle
audience: mail.internal # resource indicator, RFC 8707
token: { ttl_seconds: 120 } # short-lived; re-exchange per call
may_delegate: false # this authority stops here
default: denyFails the build on an over-broad, audience-unrestricted, or over-long hop; no real system touched.
# sanitized: static check over the delegation ledger
def gate(ledger, max_depth=1):
for hop in ledger:
if not subset(hop.scope, hop.next_consumes):
fail(f"{hop}: scope broader than downstream consumes")
if hop.audience is None:
fail(f"{hop}: token has no audience restriction")
cap = 120 if hop.boundary == "external" else 900
if hop.ttl_seconds > cap:
fail(f"{hop}: token lifetime {hop.ttl_seconds}s exceeds {cap}s")
if hop.may_delegate and hop.depth > max_depth:
fail(f"{hop}: delegation depth {hop.depth} exceeds {max_depth}")
if hop.owner is None:
fail(f"{hop}: no owner")
passed()Glossary
- Delegation Ledger
- A living record of every hop in an agent's chain of borrowed authority, recording the acting principal, the principal it acts as, scope, audience, boundary, lifetime, and delegation permission.
- Workload identity
- The identity a running agent process authenticates as — its own service principal or managed identity — distinct from any user it acts on behalf of.
- On-behalf-of (OBO)
- An OAuth token-exchange flow (RFC 8693) in which an agent trades a user's token for a downstream token that acts as the user with reduced scope and a specific audience.
- Audience restriction
- Binding a token to the specific resource permitted to accept it (RFC 8707 resource indicators), so it cannot be replayed against a different tool.
- Delegation depth
- The number of hops a borrowed authority is allowed to travel through agents and sub-agents before it must stop.
- Ambient authority
- Authority exercised with no explicit principal behind the action — typically an agent falling back to its own broad workload identity for a user-delegated task.
References
- OWASP Top 10 for LLM Applications (LLM06 Excessive Agency, LLM08 Vector & Embedding Weaknesses)
- OWASP Agentic Security Initiative — Agentic AI Threats and Mitigations
- MITRE ATLAS — Adversarial Threat Landscape for AI Systems
- NIST SP 800-207 — Zero Trust Architecture
- NIST SP 800-63-4 — Digital Identity Guidelines
- RFC 6749 — The OAuth 2.0 Authorization Framework
- RFC 8693 — OAuth 2.0 Token Exchange
- RFC 8707 — Resource Indicators for OAuth 2.0
- N. Hardy (1988), The Confused Deputy, ACM SIGOPS Operating Systems Review
- Saltzer & Schroeder (1975), The Protection of Information in Computer Systems, Proc. IEEE
- NIST AI Risk Management Framework (NIST AI 100-1)