FlawOpen

FlawOpen/Reference/AI Agent Tool Scoping: Least Privilege & Auth

AI Agent Tool Scoping: Least Privilege & Auth

Architecture guidance AI & Agent Security · OWASP LLM06:2025
ELI5 — The cabinet key and the visitor badge

A temporary worker needs to check one order. A master key would also reveal other people’s orders. An AI tool needs the same boundary: the model may suggest an order number, but the service must use the authenticated user identity to decide what data to return. Model output is not authorization.

Excessive functionality: A tool exposes actions beyond the task.
Excessive permissions: The tool identity can reach data or actions beyond its task.
Excessive autonomy: High-impact operations proceed without an independent approval gate.

How excessive agency creates risk

OWASP describes excessive agency as excess functionality, permissions, or autonomy. Risk depends on the tools exposed and the authority their identity has in downstream systems. Ambiguous or manipulated input may lead the model to choose an unsuitable tool, but only independent service authorization decides whether access is allowed. The read-only example below illustrates a missing per-user scope check; it is not a real incident. See AWS guidance on authorizing every tool invocation. Verify that your runtime propagates this request-local context into tool execution; if it does not, missing context must deny access rather than fall back to a shared identity. OWASP LLM06:2025 — Excessive Agency; AWS Agentic AI Lens — Secure agent tool usage. Python contextvars documentation.

agent_tools.py — unscoped readUNPATCHED FLAW
def lookup_order_status(order_id: int):
    # Agent tool uses a broad service identity; no user/tenant boundary.
    stmt = select(Order.status).where(Order.id == order_id)
    return session.scalar(stmt)
agent_tools.py — user-scoped readHARDENED PATCH
from contextvars import ContextVar
from pydantic import BaseModel, Field
from sqlalchemy import select

class OrderLookupSchema(BaseModel):
    order_id: int = Field(gt=0)

principal_ctx: ContextVar[Principal] = ContextVar("principal_ctx")

# Auth middleware sets this request-local context only after verifying the caller.
def handle_agent_request(request):
    principal = authenticate(request)
    token = principal_ctx.set(principal)
    try:
        return agent.invoke(request.prompt)
    finally:
        principal_ctx.reset(token)

@agent.tool(args_schema=OrderLookupSchema) # tool schema exposes order_id only
def lookup_order_status(order_id: int):
    try:
        principal = principal_ctx.get()
    except LookupError:
        raise PermissionError("Missing verified principal")
    stmt = select(Order.status).where(
        Order.id == order_id,
        Order.owner_id == principal.user_id,
    )
    return session.scalar(stmt)

A possible failure path is conditional

1

The model receives a request or external content

The agent selects a tool and arguments from context that may be ambiguous or manipulated.

2

A tool uses an overbroad identity

Without user authorization in the service, a valid lookup may reach records outside the caller’s scope.

3

The service enforces—or misses—the policy

Downstream authorization tied to the authenticated principal limits the response; the model does not decide access.

Production security review

Explore related security topics:Complete Security Directory →

Framework mappings

See also AI Agent Security: MCP & Prompt Injection — FlawOpen MCP Security: Tool Boundaries & Data Exposure | FlawOpen AI Agent Tool Security: Least Privilege and Isolation Claude Code MemoryTrap: AI Memory Poisoning AI Agent Sandboxing: Containers, gVisor & MicroVMs