Vulnerability

Excessive Agency in LLM Applications
detect, understand, remediate

When an LLM application grants the model authority to take actions through tools or function calls, the question is no longer whether the model produces the right text, but whether the application gave the model authorities it should not have. OWASP ranks the class LLM06:2025 Excessive Agency.

No credit card required. Free plan available forever.

Severity

High

CWE ID

CWE-250

OWASP Top 10

LLM06:2025 - Excessive Agency

CVSS 3.1 Score

9.6

What is excessive agency in LLM applications?

Excessive agency is the vulnerability class where a large language model is granted authority to take actions, and the authority exceeds what the model deserves. The model can call a function, invoke a tool, query a database, send an email, edit a record, charge a card, deploy code, open a ticket, or read another user's data. Each grant is a delegated authority from the application to the model. When the grants are too broad, when their parameters are not validated, when one model identity stands in for many users, or when high-impact actions fire without an explicit human approval step, an attacker who controls the prompt also controls the action. The 2025 OWASP Top 10 for Large Language Model Applications lists the class as LLM06:2025 Excessive Agency.

The vulnerability is the fourth corner of LLM application security. The prompt injection page covers the input-side risk where the attacker overrides the model. The indirect prompt injection via RAG page covers the data-side risk where the payload arrives through retrieval. The improper output handling in LLM applications page covers the output-sink risk where the model's answer reaches a renderer, query, or fetch target without sanitisation. Excessive agency is the action dimension: even with a perfectly aligned model, a perfectly sanitised input, a perfectly filtered retrieval source, and a perfectly encoded output, the question of what the model is allowed to do remains a security decision the application has to make in code.

For internal AppSec, product security, AI engineering, ML platform, and security engineering teams, excessive agency is the entry on the LLM Top 10 that turns a contained prompt injection into a real-world consequence. The bug rarely lives in the model. It lives in the tool registration, the permission scope, the parameter schema, the actor identity the tool runs under, and the human approval step the team did not add. The fix is uncomplicated in principle and operational in practice: apply least privilege to every tool grant, schema-validate every argument, re-authorise each call against the user identity rather than the model's reasoning, separate high-impact actions behind an explicit human approval, and log every tool invocation with the prompt, parameters, actor, and outcome on a record an auditor can read.

The agency surface

Tool grants and function calls

A registered function the model can invoke. send_email, refund_order, create_user, update_record, run_query, schedule_meeting, deploy_app. Every entry in the tool registry is a delegated authority. The set of tools the agent can reach is the upper bound on the blast radius of any injection that lands.

Database and storage handles

The model can read or write a row through a tool. The handle runs under a service identity that often has broader permissions than the requesting user. A read tool exposed without per-user scoping returns data across tenants on the first injection that asks the right question.

Outbound HTTP and webhook actions

An agent fetches a URL, posts to a webhook, or calls a partner API. The fetcher inherits whatever credential the tool was registered with. Where the credential is broad (workspace-wide token, admin API key), one injection turns into a cross-system action.

Code execution and notebook runners

A data-analysis assistant, a research agent, or a CI helper hands the model a code-execution tool. The sandbox runs with environment variables, mounted volumes, and a network namespace. Each one is an authority the model now wields without an authenticated user behind it.

File system and document writes

A report-generation tool writes a file to a shared drive. A document agent updates a wiki page. A code agent commits to a repository. The tool grant is the write authority on the surface; the actor identity captured in the audit log is often the model's, not the user's, which breaks accountability.

Privileged or destructive operations

Tools that delete data, revoke access, charge cards, ship orders, change configuration, rotate keys, or deploy production. Each one is a separate authority that should be separately granted, separately scoped, separately logged, and (for most of them) separately confirmed by a human before the model can fire it.

Agent-to-agent delegation

A parent agent calls a child agent that has its own tool set. The child inherits or is granted authorities the parent did not have. The composition turns excessive agency into an emergent property the engineering team did not register in any single tool list.

Persistent memory writes

A long-running agent stores facts, preferences, or instructions into long-term memory. A write authority on memory is an authority to plant instructions for every future session that retrieves the same memory. The discipline that internal teams apply to persistent state on the rest of the application applies here too.

How it goes wrong

1

Excessive functionality

A tool is registered with more capability than the feature needs. A list_orders tool also supports update_orders and cancel_orders behind the same registration. An email-summariser agent has a send_email tool because the engineering team registered the full provider SDK rather than the read-only subset.

2

Excessive permission scope

The tool runs under a service identity with workspace-wide, tenant-wide, or admin-wide scope. The user behind the request can only see their own records; the tool can see everyone's. One injection turns the user's session into the service identity's session.

3

Excessive autonomy on high-impact actions

A delete_account tool, a charge_card tool, a deploy_production tool, or a rotate_keys tool fires without an explicit human approval step. The agent reasons that the action is appropriate; the application accepts the reasoning and fires the call. The model becomes the approver of its own decisions.

4

Missing parameter schema

The tool accepts arguments the model generates without a strict schema. A refund_order tool expects an order_id and an amount; the model returns ANY_ORDER_ID and a large amount inside a prompt the user never asked. The application validates nothing and the refund processes.

5

Authorisation reads the model rather than the user

The tool checks whether the action is appropriate by asking the model. The check is recursive on the same untrusted source. The application's authorisation layer needs to read the user identity, role, scope, and policy from the request context, not from the model's self-reported intent.

6

Tool composition through agent chaining

A parent agent calls a child agent that has tools the parent does not. A research agent calls a writer agent that has a publish tool. The composition creates an emergent authority that no single tool registration captured. The audit log shows the child fired the action; the trigger came from the parent reasoning the model produced.

7

Single service-account identity for many users

Every tool call from every user runs under one service identity. The user-attribution on the audit log is at best the prompt session. Per-user revocation, per-user rate limiting, per-user blast-radius capping all fail because the identity layer cannot distinguish the requesting user from the next requesting user.

8

Token, key, or secret in the tool registration

A tool was registered with a long-lived bearer token, a workspace admin key, or a cloud provider root credential. The model can call the tool and the tool calls the upstream API with the credential as-is. The blast radius is the entire credential, not the user's scope.

9

No tool invocation log on the operating record

The application calls tools and the only record is the LLM provider's opaque trace. The security record has no prompt, no parameters, no actor, no outcome, no payload. Post-incident reconstruction is impossible because the application never wrote the evidence the responder needs.

Common causes

Registering the full SDK instead of the subset the feature needs

Engineering teams import a provider SDK that exposes every operation, then register the whole surface as agent tools. The summariser ends up with send_email because the SDK ships send_email. Tool selection at registration time is the cheapest place to apply least privilege.

Service-account identity reused across tenants

A single service identity holds the credentials every tool call uses. Per-user scoping was deferred. The injection turns the user into the service identity. Per-user OAuth, per-user scoped tokens, or per-request impersonation is the operational fix.

Approval gates skipped to keep the product fast

Human approval was framed as friction. The team removed it. The model now writes, deletes, charges, deploys, and ships on its own judgement. The first injection that lands becomes a production action because no humans were in the loop to stop it.

Trusting the model to validate its own outputs

The application asks the model whether the call is appropriate before firing it. The check is the same untrusted source. Schema validation, allow-listing, deny-listing, and authorisation belong in the application code, not in another model call.

Long-lived broad credentials in tool registrations

A bearer token with workspace admin scope, a cloud root key, or a long-lived OAuth refresh token sits inside the tool config. The credential should be the narrowest scope the feature can do its job under, with the shortest lifetime the workflow can tolerate.

No structured log of what the agent actually did

The team relies on the LLM provider's trace as the record of truth. The trace is opaque, retention-bounded, and not under the team's control. The audit record needs to live on the application's operating surface alongside every other security event.

How to detect it

Automated detection

  • SecPortal's code scanning runs against connected repositories and flags agent tool registrations where the credential is long-lived, the scope is workspace-wide or admin-wide, the parameter schema is loose or absent, the call lacks an explicit per-call authorisation read against the user identity, or a high-impact tool (write, delete, send, charge, deploy) fires without a documented human-approval gate
  • Authenticated scanning drives the LLM-backed endpoint with prompts that ask the model to invoke each registered tool with out-of-policy arguments, observes whether the call fires, captures the request, the parameters, and the resulting downstream state change as evidence on the finding
  • External scanning discovers exposed agent webhooks, tool-callback URLs, and public agent endpoints reachable from the public internet that may invoke tools without authentication or under a shared identity
  • Continuous monitoring re-runs the tool-abuse probe on a defined cadence so a new tool registration, a permission scope widened in a deployment, or a removed approval gate is caught against the previous baseline rather than waiting for the next pentest cycle

Manual testing

  • Enumerate every registered tool the agent can invoke, the parameter set, the credential the tool runs under, the identity the call is attributed to, and whether each call is logged on the application's operating record
  • For each tool, craft a prompt that asks the model to call the tool with arguments outside the registered allow-list (other tenants, other users, larger amounts, broader scopes, different recipients) and record which calls fire and what side effect the call produces
  • For agent chains, map the call graph from parent agent to child agent to tool, and confirm whether composition through delegation creates an emergent authority no single registration captured
  • For high-impact tools (write, delete, send, charge, deploy), confirm the presence of an explicit human-approval gate and that the gate cannot be skipped through prompt content alone
  • Read the audit log for the test session and confirm that each tool invocation captures the prompt that triggered it, the parameters the model produced, the actor identity attribution, the outcome of the call, and the time stamps a responder would need for post-incident reconstruction

How to fix it

Apply least privilege at tool registration time

Register the narrowest tool surface that lets the feature do its job. A summariser does not need a sender. A reader does not need a writer. A list tool does not need to bundle update or delete. The model should not have authorities the application would not give a trusted backend script written for the same purpose.

Bind every tool argument to a strict, validated schema

Define every tool with a JSON Schema, a Pydantic model, a Zod schema, or an equivalent strongly-typed contract. Reject any call whose arguments do not validate. Treat allowed-value enums as part of the schema for fields like currency, role, status, and recipient. Refuse open-ended string parameters where an allow-list would do.

Re-authorise every tool call against the requesting user identity

Read the user identity, the role, the scope, and the policy from the request context for every tool call. Do not rely on the model's reasoning about what the user can do. Run the same authorisation pass the rest of the application runs against a manual API request from the same user.

Require explicit human approval for high-impact actions

Write, delete, send, charge, deploy, rotate, and similar actions need a human in the loop. Surface the proposed call, the parameters, and the consequence to a person, and fire only on positive approval. Log the approval alongside the call as part of the evidence the responder reads first.

Scope credentials to the narrowest privilege and shortest lifetime

Replace long-lived workspace admin keys with per-user OAuth, per-request impersonation, scoped service-account tokens, or short-lived signed tokens. The credential the tool runs under should be the narrowest scope the feature can do its job under, with the shortest lifetime the workflow tolerates.

Separate identity per requesting user

Run tool calls under an identity that traces back to the user behind the request. Per-user OAuth, per-user impersonation, or per-request short-lived tokens make per-user revocation, per-user rate limiting, and per-user blast-radius capping possible. The audit record gains an actor field the application can defend.

Constrain agent chain composition

For multi-agent systems, document the call graph. Refuse delegation that composes authorities a single agent should not have. Where delegation is unavoidable, propagate the requesting user identity through every hop and re-authorise at the child boundary against that identity.

Rate-limit and quota-limit every tool

Per-user, per-session, per-day, per-tool, per-action-type. Excessive agency at scale is the difference between one charge and a thousand. Hard quotas catch the abuse before the per-call authorisation finishes investigating the first occurrence.

Log every tool invocation on the application's operating record

Capture the prompt that triggered the call, the model that produced the parameters, the parameters themselves, the actor identity the call ran under, the upstream response, the resulting state change, and the time stamps. Keep the record on the security operating surface alongside every other finding and event, not only in the LLM provider's opaque trace.

Re-run the tool-abuse regression probe on every model, prompt, and tool change

A new tool registration, a widened permission scope, a removed approval gate, a prompt change, or a model upgrade can re-open a closed excessive-agency finding. Treat the tool-abuse probe as a first-class CI gate alongside unit and integration tests, and keep the canary prompts in the test suite where the team will see them.

What this looks like in SecPortal

Finding record with prompt, tool, parameters, and outcome

The finding captures the original prompt, the tool the agent invoked, the parameter set the model produced, the actor identity the call ran under, and the observed state change (the email sent, the refund processed, the record updated, the file written, the API called). The evidence is what AppSec, product security, and AI engineering need to reproduce the abuse against the same surrounding code path.

Code scanning across tool registrations

Code scanning runs against connected GitHub, GitLab, and Bitbucket repositories. Findings surface at tool-registration sites where the credential scope is too broad, the parameter schema is loose or absent, the authorisation check reads the model rather than the user, or a high-impact tool lacks a documented human-approval gate. The remediation lands at the registration site rather than at a perimeter filter.

Authenticated scanning with tool-abuse payloads

Authenticated scanning runs against the LLM-backed endpoint with a curated set of tool-abuse prompts under a real session. Each probe records whether the tool call fires, the parameters the model produced, and the downstream state change, so the finding ties to a concrete authority misuse rather than to a model output alone.

Continuous monitoring against tool registration drift

Continuous monitoring re-runs the tool-abuse probe on the configured cadence. A new tool registration, a permission scope widened in a deployment, or a removed approval gate that re-opens a previously closed finding shows up against the baseline rather than waiting for the next pentest cycle.

Retest after the remediation ships

Once the fix deploys (the credential is narrowed, the schema is tightened, the approval gate is added, the per-user authorisation is wired), a targeted retest replays the original tool-abuse prompt against the new registration and records the post-fix response on the finding. The finding closes against the evidence rather than against a developer assertion that the registration is now safe.

AI-assisted writeups with explicit honest scope

AI reports generate the writeup, the executive summary, and the developer-facing reproduction steps from the finding record. The narrative stays within the verified evidence on the finding (the prompt, the tool call, the parameters, the outcome) and does not invent guardrails, sandbox behaviour, or runtime tooling the product does not have.

Activity log for the tool-invocation audit trail

The workspace activity log captures the security-side audit trail: who created the finding, who suppressed it, who closed it, who approved a related exception, and when the retest fired. Pair the workspace activity log with the engineering-side per-tool invocation log the application writes against every agent call so post-incident reconstruction reads from both records.

Finding overrides for documented exceptions

Where a tool grant is a deliberate test fixture or a sanctioned internal-only surface, finding overrides record the suppression rationale, the owner, and the expiry on the finding itself. The exception lives on the operating record rather than in a parallel spreadsheet.

Compliance tracking pairs the fix to control evidence

Compliance tracking maps excessive-agency findings to the controls that read against them (ISO 27001 A.5.15 access control, A.8.2 privileged access rights, A.8.3 information access restriction, A.8.18 use of privileged utility programs; SOC 2 CC6.1 logical access, CC6.3 access provisioning; NIST SSDF PW.5 secure coding; NIST AI RMF Map and Manage; ISO/IEC 42001 AI management system controls). The same finding feeds the engineering ticket and the auditor evidence pack.

What SecPortal does not do

SecPortal is the operating record where excessive-agency findings, the prompt that produced the tool call, the parameters the model returned, the actor identity, and the observed downstream effect land alongside the rest of the security backlog. The product does not act as an AI gateway intercepting tool calls between model and provider, does not host a managed agent runtime, does not enforce per-tool authorisation inside your application, does not register or manage your tool surfaces, and does not maintain a managed tool-abuse probe library that updates without your engineering team.

SecPortal does not connect to Jira, ServiceNow, Slack, SIEM, SOAR, identity providers (Okta, Entra), or external ticketing systems through packaged integrations. The discipline is the engineering practice on top of the operating record: AppSec, product security, AI engineering, and ML platform teams write the least-privilege tool registrations, the parameter schemas, the per-user authorisation checks, the human-approval gates, the rate limits, the scoped credentials, and the per-call audit logging in the application code itself.

Related tools and reading

Vulnerability

Prompt injection (LLM01)

The input-side hijack. Prompt injection is the entry point. Excessive agency is what gives the entry point a payload that reaches into the real world through a tool call.

Vulnerability

Indirect prompt injection via RAG

The data-side hijack. Excessive agency turns an indirect injection into a tool call the agent fires without the original user ever asking. The two pages read together for agent threat modelling.

Vulnerability

Improper output handling in LLM apps

The output-sink risk. Improper output handling asks what the application does with the model's answer. Excessive agency asks what authorities the application gave the agent in the first place.

Vulnerability

System prompt leakage (LLM07)

The disclosure dimension. When the system prompt leaks, the attacker reads the full tool registration as an architecture diagram of the agent's outbound capability. The two pages read together for agent threat modelling.

Vulnerability

Broken access control

The classical access-control discipline that extends naturally to agent tool calls. The application must read the user identity, role, scope, and policy for every tool invocation, not the model's reasoning.

Vulnerability

Broken function level authorization

The function-level authorisation pattern transfers directly to tool registrations. Each tool is a function. Each invocation needs its own per-user authorisation read against the requesting context.

Vulnerability

Server-side request forgery

Where the agent fetches whatever URL the model proposes. The per-feature allow-list and the link-local block-list patterns transfer directly to agent outbound HTTP tools.

Vulnerability

Command injection

Where a code-execution agent runs model-produced commands. Sandboxing, argv arrays, network egress controls, and credential isolation transfer directly to agent code-execution tools.

Blog

OWASP Top 10 for LLM applications explained

The full 2025 LLM Top 10 reading: LLM01 Prompt Injection, LLM05 Improper Output Handling, LLM06 Excessive Agency, LLM02 Sensitive Information Disclosure, and the rest of the list in operating context.

Vulnerability

Unbounded consumption (LLM10)

The resource dimension. Where excessive agency asks which tools the agent can fire, unbounded consumption asks how many times the agent is allowed to fire any of them per trace and at what total token, dollar, and inference-time budget.

Framework

NIST AI Risk Management Framework

The Map, Measure, and Manage functions read directly against tool-permission inventories, per-user authorisation evidence, and human-approval gate documentation the engineering programme produces.

Framework

ISO/IEC 42001 AI management system

The control objectives covering AI system lifecycle, secure development, accountability, and human oversight pair directly to excessive-agency remediation evidence.

Framework

OWASP and the LLM Top 10

The OWASP hub including the 2025 LLM Top 10 list where LLM06 Excessive Agency sits alongside LLM01 Prompt Injection and LLM05 Improper Output Handling.

Blog

Secure code review for AI-generated code

The code-review playbook for the upstream half of agent security: how to review the registration site, the schema, the credential, and the approval gate before they reach production.

Compliance impact

Track LLM excessive-agency findings end to end

SecPortal records excessive-agency findings against the application, attaches the prompt, tool, parameters, and observed downstream effect as evidence, generates AI-assisted writeups, and tracks the fix through retest. Start for free.

No credit card required. Free plan available forever.