Back to the map

Module 18 · Safety and security · Lesson 3 of 6

Excessive agency and least privilege for tools

An agent with more permission, functionality or autonomy than its task needs: minimal tool sets, read-only by default, per-user credentials, gates on irreversible actions, spend limits, separation of duties, audit and a kill switch.

CoreMust-knowMid 12 minPro Updated Nov 2026

Why it matters

Excessive agency made the biggest climb on the 2026 OWASP list, to third, because the thing that changed between chat products and agents is that models act. A chat product that is wrong produces a wrong paragraph. An agent that is wrong, or injected, sends the email, approves the refund, drops the table. The risk has three faces: excessive permission (the credential can do more than the task), excessive functionality (the tool list holds things the task never needs) and excessive autonomy (the agent acts with nobody looking). Interviewers ask because the controls are design decisions, and they want to see you make them before the prompt is written.

The idea

The blast radius is the permission model

An agent's possible harm is bounded by what its tools can do with the credentials they hold, multiplied by how long it can run unobserved. The prompt shapes what the agent is likely to do; the permission model bounds what it can do. The Prompt injection lesson established that content can override the prompt, so the bound is the only part you can rely on. Design it first: list the actions the task needs, the data each touches, which are reversible, and whose identity the agent acts under. The prompt comes after.

The controls

Minimal tool sets per task. Build the list from the task, not from what the platform offers. A ticket-triage agent needs read ticket, search knowledge base and add internal note. It does not need close ticket, refund or send email, even though the helpdesk API has them. If a workflow has three stages, each stage gets its own list; the Routing and Orchestrator-workers lessons give the shape.

Read-only by default. Start with reads. Add each write with a written reason, and prefer a write that creates a draft over one that publishes.

Credentials scoped to the user, not the agent. The agent acts with the caller's permissions, obtained through the host as the MCP server lesson describes, so an injected instruction to read another customer's record fails at the data layer. A shared service account with admin rights is the most common finding in agent reviews.

Confirmation gates on irreversible actions. Send, pay, delete, deploy, publish and anything that leaves your boundary wait for a human who sees the exact arguments. Reversible actions (draft, stage, flag) run freely. The Stop conditions lesson covers keeping the gate from becoming a reflex.

Rate and spend limits. Per user, per agent, per tool: at most this many sends an hour, this much spend a day, a hard ceiling on tokens per task. A runaway loop or a bulk exfiltration hits the ceiling before it reaches the news.

Separation of duties. The agent that reads email cannot send it; the one that drafts a refund cannot approve it. Two agents with disjoint tools and a human or a deterministic check between them, so an injection in the reading agent has nothing to act with.

Sandboxing. Code execution, file access and browsing run in an isolated environment with no credentials and an egress allow-list; the Code execution and sandboxes lesson has the detail.

Audit of every action. Every tool call logged with the user, the tool, the arguments, the result and the trace it belongs to. Without it you cannot answer the first question after an incident.

Kill switch. One flag that stops every agent in a tenant or the fleet, tested before it is needed, owned by someone on call.

broad agentagent: admin tokenreadsenddeletedeployone injection: all of itscoped and gatedagent: user tokenreaddrafthuman gatesendone injection: a draft
Same task, two permission models. On the left an injection reaches everything the admin token can do; on the right it reaches a draft and a gate.

Reviewing a tool list

Take the agent's tool definitions and ask of each: which task step needs it; is it a read or a write; is it reversible; which credential does it run under and who scoped that; what is the worst argument an injected model could pass; is it rate-limited; is it gated. A tool with no task step is removed. A write with no gate and no reversal is the finding. Record the answers beside the schema, so the next reviewer sees the decision and not just the tool.

{
  "name": "draft_reply",
  "description": "Create an unsent draft reply to a ticket. A human sends it.",
  "input_schema": { "type": "object", "properties": { "ticket_id": { "type": "string" }, "body": { "type": "string" } }, "required": ["ticket_id", "body"] },
  "review": { "scope": "tickets:write:draft", "reversible": true, "gate": "none", "limit": "60/hour" }
}
 Broad agentScoped toolsScoped plus gates
Blast radiusEverything the service account can doWhat this task's tools can do as this userReversible actions only, until a human approves
User frictionNoneNone; some tasks need a second agentA confirmation per irreversible action
What an injection can doSend, delete, pay, exfiltrateRead what the user can read; write draftsPropose; the human decides
Audit storyA service account did somethingThis user, this tool, these argumentsThe same, plus who approved
FitDemosInternal assistants over user-owned dataAnything that sends, pays, deletes or deploys
Excessive agency and least privilege for tools · Backplane