Agents and tools

AI agent permissions: how to scope tools and credentials

AI agent permissions: give each tool one task, one scoped credential and an approval rule. Includes a copyable permission matrix and a 7-step test plan.

Short answer

AI agent permissions should follow the task, not the agent. Give each tool one job, run it with the calling user's credential at the lowest scope, check every call in code outside the model, and gate high-impact actions. A permission matrix, with one row per tool and action, makes gaps visible before a tester finds them.

AI agent permissions should be small, per tool and tied to the user. A text input can steer an agent, so assume that someone who should not make a call you allow can still attempt it. Your permission design limits the damage. The method builds on OWASP's mitigations for excessive agency.

What is the right permission model for an AI agent?#

The right model gives each tool one task, runs it with the calling user's credential at the lowest scope, checks each call in code, and gates high-impact actions. Four rules apply.

  1. One tool, one task. Split broad tools. A tool that reads mail must not also send it.
  2. User context. OWASP advises that actions taken for a user run on downstream systems in that user's context, with the minimum privilege needed. For a repo reader, that means the user signs in with OAuth at the smallest scope.
  3. Mediation in code. Check every request against policy outside the model. OWASP calls this complete mediation. The check can sit in the tool, in a policy decision point before the downstream system, or in the downstream system.
  4. Graduated approval. OWASP describes a policy that audits, warns, blocks or escalates. Low-risk and reversible actions can run on their own. Irreversible ones go to a human.

Why do agents end up over-permissioned?#

The quickest way to make a demo work is a broad token, and nobody narrows it later. OWASP lists the typical cases under excessive permissions and excessive functionality.

Shortcut Result
One admin API key in the agent config Every user's request runs as admin
Read tool bound to a database role with write grants A bad query can change or delete data
Tool kept from an earlier trial Unused functions stay reachable
Open-ended tool: "run a command", "fetch any URL" Scope of action is unbounded
All OAuth scopes requested up front A stolen token opens everything
Agent-to-agent calls use the calling agent's identity The original user's limits are lost

The MCP spec makes the same point about tokens. Its Scope Minimization section lists as common mistakes publishing every scope in scopes_supported, using wildcard or omnibus scopes, and returning the whole scope catalog in every challenge. It asks for a small starting scope and step-up requests for privileged actions.

How do you build a permission matrix?#

Build a permission matrix with one row for each tool and action, and fill in the identity, scope, check and approval rule. Write it before launch and keep it with the code.

Agent permission matrix template

Copy the table and add one row per tool and action. An unknown cell is a finding.

Tool Action Needed for task Acts as (identity) Granted scope Who enforces the check Reversible? Approval rule Limit Log fields
crm_read Read contact Answer sales questions Calling user (OAuth) contacts:read CRM, row-level rules n/a None 60/min user, tool, contact ID
crm_update Edit contact note Log call notes Calling user contacts:write:notes Tool code, field allowlist Yes (history) Auto, show diff 20/hour user, field, old, new
email_draft Create draft Reply help Calling user mail:drafts Mail API Yes None 20/hour user, draft ID
email_send Send mail Send approved draft Calling user mail:send Tool code, recipient policy No Human click per message 5/hour user, recipients, hash of body
files_read Read file Summarize files Calling user files:read own drive Storage ACL n/a None 30/min user, file ID
payments_refund Refund Support refund under cap Service account, capped refund:create up to a cap Payments policy engine No Human above the cap, block above hard cap 3/day user, order, amount
web_fetch GET a URL Read help pages Egress proxy Allowlisted hosts Proxy n/a Block unlisted hosts 10/min user, URL, status

Then check the matrix against five questions:

  1. Does any row act as a shared identity? If yes, can the user reach more through the agent than directly?
  2. Does any irreversible action run with no human and no cap?
  3. Does any tool combine private data, untrusted input and an outbound path? Gate that combination.
  4. Is each "who enforces" cell outside the model?
  5. Can you tell from the log who asked, which tool ran and what changed?

What does a permission failure look like in practice?#

Text the user did not write can make a permitted call that the user did not want. The GitHub MCP disclosure from Invariant Labs, published 26 May 2025, is a documented example.

A malicious issue in a public repository steered an agent to read private repository data and publish it in a pull request. The authors state it was "not a flaw in the GitHub MCP server code itself." The agent held a token that reached both public and private repos, and the demo used "Always Allow" confirmations. Invariant recommends least-privilege repo access and runtime monitoring, and it sells related tooling.

In matrix terms, the scope column was wider than the task, and the approval column was empty. OWASP's Agentic Top 10 (published 9 December 2025) gives such cases names: ASI03 Identity & Privilege Abuse and ASI02 Tool Misuse. See the OWASP agentic guide.

How do testers test agent permissions?#

Testers compare what the user can do directly with what the agent can do for that user, then try to cross the line with test accounts. The test needs at least two users with different rights.

  1. Read the matrix. Ask for it. If it does not exist, build it from config, tool schemas and traffic.
  2. Direct versus agent. As a low-rights user, ask the agent for data or actions that only a high-rights user may have. The agent should refuse or fail at the downstream system.
  3. Cross-user. As user A, ask for user B's record by name and by ID.
  4. Trigger test. Place a marker instruction in a document or tool result and see whether the agent attempts an out-of-scope call. Record whether the downstream check blocked it.
  5. Scope check. Inspect issued tokens (in a test environment). Compare granted scopes with the matrix.
  6. Approval check. Try each gated action and note where the gate sits and what the user sees. See human approval bypass.
  7. Log check. Confirm the log shows user, tool, arguments and result.

Report each result as observed, with the request and the response. Report the controls that held as well, so fixes do not break them.

What fixes come first?#

Fix in this order: remove unneeded tools, replace shared credentials with user credentials, put the check in code, then add approval for what remains.

  • Delete unused tools and trial leftovers.
  • Replace admin keys with per-user tokens and narrow scopes.
  • Split open-ended tools into narrow ones with strict input schemas.
  • Add a policy check before each downstream call.
  • Add approval, caps and rate limits for irreversible actions.
  • Add logs that name the user and the tool.

These steps lower the likelihood and impact of misuse, but the model still reads untrusted text, so they do not make an agent safe against every attack.

Excession Labs checks these controls in scoped AI agent security assessments. We agree the scope with you in writing and test only with written authorization from the system owner. For MCP-specific token rules, read our MCP security risks guide.

Questions

Should an AI agent use its own service account or the user's credential?

Use the user's credential where the action is on the user's behalf. OWASP advises running tools in the user's context with minimum scope. A shared service account lets the agent reach data the current user could not reach.

Where should permission checks live?

In code outside the model. OWASP calls this complete mediation: validate every request to a downstream system against policy, in the tool, a policy decision point or the downstream system. A prompt rule alone is not a check.

What is the agent's identity in logs?

Log both the user and the agent or tool that acted, plus the tool arguments and result. If every call shows as one service account, you cannot tell a user action from an agent action during an incident.

Do I need a new permission model for agents?

Mostly no. Use your existing roles, OAuth scopes and database grants. The new part is that the caller is a model that can be steered by text, so assume any permitted call can be attempted.

Sources

  1. OWASP Top 10 for LLM Applications 2026: LLM03 Excessive Agency (mitigations) (checked 9 November 2026)
  2. OWASP Top 10 for Agentic Applications (OWASP GenAI blog, 9 December 2025): ASI02 Tool Misuse, ASI03 Identity & Privilege Abuse (checked 9 November 2026)
  3. Model Context Protocol specification 2026-07-28: Security Best Practices, Scope Minimization (checked 9 November 2026)
  4. Model Context Protocol specification 2026-07-28: Authorization (checked 9 November 2026)
  5. Invariant Labs, GitHub MCP exploited: accessing private repositories via MCP (26 May 2025) (checked 9 November 2026)