How to Secure LLM Tool Calls: Authorization, Scope, and Injection Prevention
LLM tool calls let AI agents act on real systems — and create a new attack surface. Learn how to enforce authorization at the tool layer and prevent injection.
LLM tool calls are now the standard mechanism for building AI agents that interact with real systems: reading database records, writing files, sending emails, calling third-party APIs. When you enable function calling in Claude, GPT-4, or Gemini, you are giving a language model the ability to trigger real-world side effects based on its interpretation of text. That is a fundamentally different authorization problem from a traditional API call, and most engineering teams are solving it with the wrong model.
In a traditional API call, your code constructs the request with known, application-controlled arguments. In an LLM tool call, the model decides which function to call and what arguments to pass, based on natural language input that may include text the user typed, text retrieved from a database, or text injected by an attacker who has found a way to influence the model's context. If your authorization layer only checks whether the user has permission to call a given endpoint, you are trusting the model's judgment unconditionally — and an attacker who can influence the model's input can direct its tool use.
This guide covers the security model of LLM tool calls, the vulnerability classes they introduce, and the controls needed to close them. If your application uses the Model Context Protocol (MCP), the MCP server security guide covers the protocol-specific attack surface; the authorization principles here apply to both. For a broader production checklist for AI agents, see the guide to securing AI agents in the enterprise.
Why LLM Tool Calls Are a Distinct Security Problem
Traditional application code has a fixed control flow: a known sequence of function calls executed with arguments constructed by the application itself. LLM-driven tool calls break that assumption. The model receives input and dynamically decides which function to invoke and what arguments to pass. This shifts the security boundary: you are no longer asking only whether the calling user has permission to access a resource, but whether the model's decision to access that specific resource with those specific arguments is legitimate for this user and this task.
- →In a regular API, the calling code is trusted by definition. In an LLM tool call, the calling "code" is model output generated from untrusted input that may contain attacker-controlled content.
- →The model has no inherent concept of authorization scope. It passes whatever record ID or file path it believes is correct based on context — including IDs it infers, extrapolates, or is manipulated into using.
- →Tool call arguments constructed from retrieved content inherit the trust level of that content. A document from a user upload can contain text that shapes the model's next tool call.
- →The model can chain tool calls, with each call's output feeding the next decision. A single injection point can propagate through an entire agent loop, escalating privileges with each step.
Common Vulnerabilities in LLM Tool Call Implementations
These are the vulnerability patterns that appear most frequently in security reviews of AI agent integrations. Each has a root cause in conflating model trust with application authorization.
- →IDOR via model-generated record IDs: the model constructs a tool call that accesses a record ID it inferred from context — a sequential integer, a UUID pattern, or an ID mentioned in an unrelated part of the conversation. The tool executes without checking whether the authenticated user owns that record, producing horizontal privilege escalation across any user in the system.
- →Cross-tenant data leakage: a multi-tenant application queries the database with a model-generated tenant identifier rather than the server-side session's tenant. If the model is manipulated into generating a different tenant ID, the query returns a different tenant's data.
- →Privilege escalation via chained calls: an injection in a retrieved document causes the model to invoke a write tool — send_email, update_permission, delete_record — that it would never invoke under the declared task, exploiting the agent's legitimate credentials.
- →Exfiltration via outbound tools: agents with access to outbound tools such as email, HTTP requests, or webhooks are a data exfiltration path after a prompt injection. The model is instructed to send retrieved data to an attacker-controlled endpoint using the agent's credentials.
- →Parameter injection from tool outputs: a tool that returns freeform text places it into the model context, where it can contain prompt-like instructions that influence subsequent tool calls — the indirect prompt injection path.
Enforce Authorization at the Tool Layer, Not in the Prompt
The most common secure-by-design mistake in LLM applications is placing authorization logic in the system prompt: 'You may only access records belonging to the authenticated user. Never access another user's data.' This instruction is not an access control. It is a natural language suggestion to a model that generates probabilistic output from text that may include adversarial content. Any attacker who can influence the model's context can override a prompt-level instruction with a sufficiently well-crafted injection. Authorization must be enforced at the tool execution layer, server-side, before the tool's side effects occur.
- →Implement a tool execution interceptor between the model's tool call request and the actual function execution. The interceptor receives the tool name, model-generated arguments, and the authenticated user session. Before calling the function, it checks: is this user permitted to call this tool? Is this user permitted to call it with this specific argument value?
- →The user session that populates the authorization check must come from your server-side authentication context, never from a model-generated claim. If the model's arguments include a field like 'user_id' or 'tenant_id', validate it against the authenticated session before execution.
- →For tools that read or write records associated with a specific entity, enforce ownership at the data layer: add a WHERE owner_id = :session_user_id condition to every query inside the tool, regardless of what ID the model passed. This provides defense-in-depth beyond the interceptor.
- →Authorization checks inside the tool itself are not sufficient if the tool is callable via multiple paths. The interceptor enforces the same policy regardless of whether the tool was invoked by the model, by a direct API call, or by a test harness.
Preventing Prompt Injection via Tool Outputs
Tool outputs are returned to the model as new context, creating the indirect prompt injection vector: an attacker plants malicious instructions in a resource the agent will retrieve — a document, a database record, or an email — and those instructions enter the model context as tool output, influencing subsequent tool calls. The consequences at the tool execution layer are higher-severity than text-output injection because they translate directly into real-world actions: a file is written, an email is sent, a record is modified.
- →Return structured data from tools, not freeform text. A tool that retrieves a user record should return a typed JSON object with specific fields, not a free text summary. Structured responses limit the surface area that injected instructions can occupy.
- →Validate tool outputs before returning them to the model context. For tools that return user-generated or externally sourced content, check for instruction-shaped text: imperative sentences, role-override phrases such as 'Ignore previous instructions' or 'You are now...', and system-prompt markers.
- →Treat tool outputs from external sources as untrusted input, applying the same scrutiny as user-provided text. A tool that fetches a web page, reads an email, or processes an uploaded file is retrieving content from an environment the attacker may control.
- →Apply a dual-model pattern for high-stakes tool outputs: route tool outputs through a lightweight judge model that checks for injection patterns before they reach the main reasoning context. The latency cost is justified for agents with access to write tools, outbound tools, or sensitive data.
Apply Least-Privilege to Tool Scope
Every tool you expose to an LLM session extends the potential impact of a successful injection or model error. An agent answering questions from a knowledge base does not need write tools. A support agent does not need tools that modify billing records. A document summarizer does not need tools that call outbound APIs. The principle of least privilege applies to tool availability: each agent session should have access to the minimum set of tools required to complete its declared task.
- →Define task-scoped tool sets at session initialization. When a user starts an agent session for a specific purpose, construct the tool registry with only the tools relevant to that purpose — not the full tool catalog. Store the allowed set by task type and look it up at session start.
- →Separate read and write variants of tools even when the underlying data layer has combined access. The model must explicitly invoke the write variant to trigger a write, creating a decision point where the interceptor can apply additional scrutiny before the action proceeds.
- →Time-bound tool scope for sensitive operations: authorization for privileged actions should expire after the action completes or after a maximum session duration. Persistent elevated tool access in long-running sessions accumulates risk and widens the injection impact window.
- →Audit tool call frequency per session. Unusually high call volume, tools called outside the declared task type, or access to records not associated with the authenticated user are signals of injection activity or model reasoning failure that warrant investigation.
Parameter Validation and Schema Enforcement
LLM tool call arguments should be validated against a strict schema before execution, treating model-generated values as untrusted input just as you would treat user-submitted form data. Validation at this layer catches injection patterns the model included in arguments, out-of-range values it inferred incorrectly, and argument types that differ from what the tool expects.
- →Define JSON Schema for every tool's arguments and validate model output against it in strict mode: reject any argument not in the schema, any argument of the wrong type, and any argument that fails a custom semantic validator. For TypeScript projects, generate schemas from tool type definitions; for Python, use Pydantic with strict mode.
- →Apply semantic validation beyond type checking for high-risk arguments. A record ID field should validate that the value matches your ID format — UUID, snowflake, or integer range. A query string field should check for SQL keywords if it feeds a query builder. A URL argument for a webhook should validate against an allowlist of approved domains.
- →Never construct database queries or shell commands from raw model-generated string values. Use parameterized queries inside tools, with the model-generated value passed as a parameter, not interpolated into a query string. This prevents the SQL injection path that opens when model output feeds directly into a query template.
- →Rate-limit tool calls per session, per user, and per tool. Automated prompting via the API can generate high-frequency call sequences that probe authorization controls or extract data at scale. Per-session rate limits add friction for automated abuse without affecting legitimate interactive use.
Observability and Logging for Tool Call Security
Security controls without observability are incomplete. You cannot detect a tool call authorization bypass after the fact without logs that capture what tool was called, with what arguments, by which user, and in response to which input. DeployReady includes tool call audit checks in its AI application readiness assessment, flagging agent integrations that lack structured logging or authorization enforcement at the tool layer.
- →Log every tool call invocation at the interceptor level: timestamp, user session ID, authenticated user identity, tool name, full argument values with sensitive fields redacted, authorization check result (allowed or denied), and execution result or error. This log is the foundation for both security monitoring and incident reconstruction.
- →Alert on anomaly patterns: tool calls to tools outside the session's declared scope, tool calls accessing records not associated with the authenticated user, unusually high tool call volume from a single session, and tool calls that return access-denied errors at the data layer, which indicate bypass attempts.
- →Use span-level distributed tracing for multi-step agent runs. Each tool call is a span; the full agent run is a trace. This lets you visualize the sequence of tool calls for any given user request and identify anomalous patterns — such as an unexpected write call following a read sequence — that would not be visible in individual call logs.
Frequently Asked Questions
What is an LLM tool call and why does it introduce security risks?
An LLM tool call is a capability in modern language models that lets the model invoke external functions by outputting structured JSON describing which function to call and what arguments to pass. The security risk is that those arguments are generated by a language model from natural language input, which may include attacker-controlled content. If your application executes model-generated tool calls without independent authorization checks, an attacker who can influence the model's input can direct it to call tools with unauthorized arguments — accessing other users' records, triggering write operations, or exfiltrating data via outbound tools.
Is it safe to put authorization rules in the system prompt?
No. System prompt authorization instructions are natural language suggestions to a probabilistic model, not enforced access controls. A prompt injection in user input or a retrieved document can override system prompt instructions. Authorization must be implemented in the tool execution layer, server-side, independent of the model. The system prompt can describe intended behavior; it cannot enforce it. This distinction is the most important security principle in AI agent development.
What is indirect prompt injection in a tool call context?
Indirect prompt injection is when an attacker plants malicious instructions in content the agent will retrieve — a document, a database record, an email, a web page — rather than in the user's direct input. When the agent fetches that content via a tool call, the instructions enter the model context as tool output and can influence subsequent decisions, including further tool calls. Mitigations include structured tool output formats, output validation before returning content to the model context, and treating all tool outputs from external sources as untrusted input.
How do you apply least-privilege to an AI agent's tool access?
Define task-scoped tool sets at session initialization: construct the available tool registry to include only the tools required for the declared task. Separate read and write variants of tools so write access requires explicit inclusion. Time-bound sensitive tool access so it expires after task completion. Audit which tools each session type actually invokes in production and prune any that appear in the registry but never in the logs — an unused tool in the registry is attack surface with no corresponding benefit.
How do vibe-coded apps typically get LLM tool call security wrong?
AI coding assistants generate tool call integrations that are functionally correct but typically lack authorization at the tool layer. The generated code passes model output directly to the tool function, queries the database with model-generated identifiers without ownership checks, and exposes the full tool catalog to every agent session. A security review of an AI-built application should explicitly audit every tool call implementation for an authorization interceptor, parameter validation against a strict schema, and scope restrictions at session initialization.
How Belsoft Helps Secure AI-Powered Products
Belsoft's security audit covers the full AI application attack surface: tool call authorization, prompt injection via retrieved content, excessive agent scope, authentication flows, and data access controls. We review the tool implementations, the authorization interceptor or its absence, the tool scope configuration, and the logging setup — then provide a detailed findings report with prioritized fixes and retest after remediation. Run DeployReady first for an automated baseline on configuration, security headers, and application-layer posture. When the automated checks are complete, a Belsoft security audit goes further: engineers who know how these AI integrations break test your tool authorization and agent attack surface by hand, then help you fix what they find.
“The model decides what to call. Your authorization layer decides whether to allow it. Only one of those should be influenced by user input.”
Written by
Marco Silva
Security Engineer, Belsoft Solutions
More from the blog
Ready to partner?
Let's talk about your company.
30 minutes. No pitch. We talk through how you run today and where AI and automation would help.
Book a free audit
