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.
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.
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 agent | Scoped tools | Scoped plus gates | |
|---|---|---|---|
| Blast radius | Everything the service account can do | What this task's tools can do as this user | Reversible actions only, until a human approves |
| User friction | None | None; some tasks need a second agent | A confirmation per irreversible action |
| What an injection can do | Send, delete, pay, exfiltrate | Read what the user can read; write drafts | Propose; the human decides |
| Audit story | A service account did something | This user, this tool, these arguments | The same, plus who approved |
| Fit | Demos | Internal assistants over user-owned data | Anything that sends, pays, deletes or deploys |