AI agent tool permissions: least privilege for LLM agents
Least privilege for AI agents: scope each tool, split read from write, run as the user, confirm irreversible actions and log every call. With a review table.
Asghar Ali · Chief Technology Officer, Kakushin.io LTD
Least privilege for an AI agent means each tool can do only what the feature needs, it acts with the permissions of the person the agent is working for, and nothing irreversible happens until that person confirms it. Those rules live in code, not in the prompt, because the model is the part you cannot trust to enforce them. OWASP's 2026 list puts Excessive Agency third (LLM03:2026) and names its three root causes: excessive functionality, excessive permissions and excessive autonomy (OWASP LLM Top 10 2026, published 3 August 2026, read on 3 November 2026).
This is for the team adding tools to an assistant: an inbox helper, a support agent that issues refunds, a copilot with database access. It covers scoping each tool, splitting read from write, when a person must confirm, why a shared service key undoes the rest, and what to log, with a permission-review table for an agent with email, database and payment tools. For the wider risk list, see the OWASP Top 10 for LLM applications in a real product.
What does least privilege mean for an AI agent?
NIST's control for it, AC-6 in SP 800-53 Rev. 5, allows "only authorized accesses for users (or processes acting on behalf of users)" that the task needs (NIST SP 800-53 Rev. 5, current release 5.2.0 of 27 August 2025, read on 3 November 2026). An agent is exactly a process acting on behalf of a user, so the old rule applies unchanged.
OWASP's three root causes become three questions for every tool:
- Functionality. Does the tool do more than the feature needs? A mail summariser that can also send and delete has excess functions, whatever the prompt says.
- Permissions. Does the credential behind it reach more than the feature needs? OWASP's example is a read tool whose database identity also has UPDATE and DELETE rights.
- Autonomy. Can a high-impact action run without anyone checking it, such as deleting a user's documents?
OWASP's agentic list adds Least-Agency: do not give a feature autonomy it does not need at all (OWASP Top 10 for Agentic Applications, December 2025, read on 3 November 2026). A button that drafts a reply is often a better product than an agent that decides when to send one.
Why can the model not enforce its own permissions?
Because what it decides to do can be wrong or steered. OWASP lists the triggers for Excessive Agency as hallucination, direct or indirect prompt injection, and a compromised tool or peer agent. Any text the model reads can change what it tries next; testing for prompt injection is how you find those paths.
So the model proposes, and code decides. OWASP's LLM03:2026 entry calls this complete mediation: authorisation is implemented in logic, and every request to a downstream system is checked against policy by the tool, by a separate policy check, or by the downstream system itself. The same entry notes that sanitising inputs and outputs is not a root control for Excessive Agency. A system prompt saying "never refund more than £50" is a hint to the model, not a limit.
How do you scope each tool?
Start from the feature, not the API you are wrapping. OWASP's first three mitigations are the fewest tools, the fewest functions in each, and narrow tools with a strict input schema instead of open-ended ones such as "run a shell command" or "fetch a URL". In practice:
- One tool per job. "Look up order status" and "issue refund" are separate, so a feature that only answers questions never receives the refund tool.
- Read and write split. A read tool has no write path in its code and no write right in its credential, so it can go to more features and the write tool to fewer.
- Arguments the code fills in. User, tenant and conversation come from the session, never from the model. It may choose which of this customer's orders to look up, not the customer.
- Limits in the tool. Recipient allowlists, maximum rows, maximum amount. OWASP's agentic list calls these per-tool least-privilege profiles: scopes, maximum rate and egress allowlists.
- Nothing left over. OWASP's examples include a tool trialled in development, replaced, and still available. Inventory the tool list the model receives in production.
Should an agent use the user's credentials or a shared service key?
The user's, scoped down, wherever the downstream system allows it. OWASP's fifth mitigation is to execute tools in the user's context, for example through OAuth with the minimum scope, and to keep the original user's context and scope across chained or delegated calls rather than relying on the calling agent's identity. Its agentic entry on identity and privilege abuse (ASI03) adds short-lived, task-scoped tokens and describes the failure where one person's agent identity is quietly used by others.
A shared service key breaks all of that at once. If the agent's database connection can read every tenant, so can one steered call, and the logs show only "the agent". When a background job needs its own identity, give it a narrow role and make the user or tenant a filter the tool or database enforces, not one the model supplies.
Read the scopes; they are coarser than they look. In Google's Gmail API, the read-only scope views mail, but the compose scope covers both drafts and sending (Gmail API scopes, read on 3 November 2026), so a "draft only" rule must also live in your tool code. Stripe's restricted keys set each resource to None, Read or Write, and its docs recommend them for keys given to AI agents (Stripe restricted API keys, read on 3 November 2026).
Keep the credential out of the model's reach. On the customer apps of a European national electricity utility, I introduced a relay-proxy architecture that removed every client API key from the shipped binaries. The same rule holds for agents: the key sits on the server behind the tool, never in the prompt, the context or the browser (secrets on the wrong side).
Which actions need a person to confirm?
Irreversible ones, outward ones and money. OWASP's LLM03:2026 entry describes a graduated policy (audit, warn, block, escalate): reversible, low-consequence actions run on their own; irreversible ones go to a person. Its example: a support bot may refund as store credit automatically, but an external payout waits for approval. The agentic list names delete, transfer and publish, with a dry run or diff before approval.
Two details decide whether confirmation works:
- Confirm the exact action, rendered by your code. Show the recipient, amount, record and text from the tool's arguments, not the model's description. A steered model can describe a harmful action in harmless words.
- Ask rarely enough to be read. If every call needs a click, people stop reading. Confirm the risky few and make the rest reversible.
What should the audit trail record?
Every tool call, with enough detail to say who did what on whose behalf. NIST's AC-6(9) asks organisations to "Log the execution of privileged functions", and OWASP's agentic threats guide names the opposite failure, repudiation and untraceability, where an agent's actions cannot be reconstructed or attributed (Agentic AI – Threats and Mitigations, v1.1, December 2025, read on 3 November 2026).
Record the user, session, tool and version, arguments, policy decision, approver and result, somewhere the agent cannot write. The agentic list suggests watching for unusual chains, such as a database read followed by an external transfer. These logs hold customer data, so give them their own access rules and retention.
Then review the grants: AC-6(7) asks for privileges to be reviewed at a set frequency and removed when no longer needed.
A permission review for an agent with email, database and payment tools
Use this table on a real agent: one row per tool action, filled in from the code and the credential, not from the design document.
| Tool action | What often ships | Least-privilege version | A person confirms when | Log |
|---|---|---|---|---|
| Read and summarise email | Full mailbox access, including send and permanent delete | Read-only scope; the tool returns only the thread the user opened | Never; it cannot change anything | Thread read, for which user |
| Draft and send email | A send tool with free-form recipients | A draft tool; recipients limited in code to the thread or an allowlist; sending is a separate step | Every send, showing the exact recipients and text | Draft, recipients, approver |
| Look up records | One database connection with an owner role; a "run SQL" tool | Named queries; a read-only role; only the columns the task needs; tenant and user filters set from the session | Never | Query name, parameters, row count |
| Change records | The same owner connection; any UPDATE or DELETE | One tool per change (for example, set ticket status); write rights on that table only; no hard delete | Bulk changes and anything that deletes | Before and after values |
| Issue a refund | The account's full secret key in the agent's environment | A restricted key; refund tied to the order in this conversation; an amount cap in code | Above the cap, and any payout to a bank account | Order, amount, approver |
| Fetch a URL or run a command | Left over from the prototype | Removed, or replaced with a narrow tool and an egress allowlist | Not applicable | Every call, if kept |
Then score each row against OWASP's three causes. A row with a broad credential is excessive permissions; a row with spare functions is excessive functionality; a row with no confirmation on an irreversible step is excessive autonomy.
A worked example (illustrative)
This example is invented to show the method; it is not a client case. A small online shop gives its support team an assistant that reads the shared support inbox, looks up orders and drafts replies, and can refund up to a set amount.
The review finds four things. The mail integration has full mailbox access because that was the default. The order lookup uses the owner database account and takes a customer email from the model, so it can look up anyone. The refund tool reads the provider's full secret key. And a URL-fetch tool from the prototype is still listed.
The fixes go in code and configuration, not the prompt. Mail drops to read-only, and drafts wait for a person to send. The lookup moves to a read-only role and takes the customer from the ticket. Refunds use a restricted key, run alone as store credit under the cap, and wait for a team lead above it. The fetch tool goes. On re-test, a test email asking the assistant to forward order details still produces an odd draft now and then, but nothing leaves without a person, and the log shows the attempt.
What this cannot tell you
- It limits damage; it does not stop steering. A well-scoped agent can still write a wrong draft. Keep testing for prompt injection.
- It assumes the app's own authorisation holds. If an API already serves one customer's record to another, fix that first; see the ID in the URL.
- It is a snapshot. New tools, scopes and models each change the table.
- It does not vet the tools themselves. Third-party tool servers are a supply-chain question (ASI04 in OWASP's agentic list).
- It sits on the basics in application security best practices.
FAQ
What is least privilege for AI agents?
Giving each agent tool only the functions, data and permissions its task needs, with the user's own scoped rights. Irreversible actions wait for a person, and every call is logged against the person it was made for.
Is an instruction in the system prompt a permission control?
No. The model can ignore it or be steered past it, so it is a hint, not a limit. OWASP's guidance is to implement authorisation in code or the downstream system and check every request before it runs.
Should every agent action need human approval?
No. Approve irreversible, outward and money actions, and let reversible, low-impact ones run with logging. If everything needs a click, people stop reading what they approve.
Can several users share one API key behind an agent?
Avoid it. One steered call could then reach every user's data, and the log cannot say whose request it was. Use each user's scoped token where the service supports it, or a narrow service role with the user enforced by code.
How often should agent permissions be reviewed?
Whenever a tool, scope or data source is added, and on a fixed schedule such as quarterly. NIST's AC-6(7) asks for privileges to be reviewed at a set frequency and removed when no longer needed.
If you want this checked
I review AI agents and LLM features for this: a tool-by-tool permission table like the one above, filled in from the code and the credentials, tool-permission and prompt-injection tests, and a written fix list. The scope is on my hire page.