OWASP Top 10 for agentic apps: what API developers need to change
Your API has rate limiting, BOLA checks, and input validation. An AI agent bypasses all three by chaining six authorized endpoints into a privilege escalation path your threat model never considered. 520 tool misuse incidents in early 2026 reporting confirm this isn't theoretical.
OWASP released its Top 10 for Agentic Applications in 2026, built by 100+ security researchers from Cisco, Microsoft, Google, and the broader community. The list targets a new threat surface: autonomous AI agents that call your APIs, retain memory, and make decisions without human approval.
The original OWASP API Security Top 10 assumes a human clicks a button and triggers one request. The agentic list assumes a machine fires 50 requests in a chain, each informed by the previous response, with no human in the loop. Same APIs, different attacker profile.
This guide covers the five OWASP agentic risks that API developers can fix at the API layer, with working code you can ship this week.
The agentic action layer: why your APIs are the attack surface
APIs have evolved into what security researchers now call the "agentic action layer." Every tool an AI agent uses, whether ordering inventory, querying a database, or sending a notification, maps to an API call. The agent doesn't interact with a UI. It reads your OpenAPI spec, discovers endpoints, and calls them in sequence.
48.9% of organizations have no visibility into machine-to-machine traffic. That means half of all API infrastructure cannot distinguish a human user from an autonomous agent. If you can't tell the difference, you can't enforce different rules.
The OWASP Agentic Top 10 covers: Excessive Agency, Prompt Injection, Supply Chain Vulnerabilities, Memory Poisoning, Tool Misuse and Privilege Escalation, Cascading Failures, Insecure Output Handling, Insufficient Logging, Data Leakage, and Inadequate Sandboxing. This guide focuses on the five risks you fix at the API layer.
1. Excessive agency: agents calling endpoints they shouldn't
A customer support agent needs to read order status. You give it an API key with access to your entire API. The agent discovers it can also cancel orders, issue refunds, and delete accounts. Excessive agency means the agent has permissions beyond its task.
This is the agentic equivalent of OWASP API5 (broken function-level authorization), but the attack vector is different. A human attacker discovers admin endpoints through source code or URL guessing. An agent discovers them through your OpenAPI spec or tool manifest. The agent doesn't need to guess; you handed it the full menu.
Fix: scoped API keys and endpoint allowlists
Create one API key per agent. Each key maps to an explicit list of allowed endpoints. Reject any request outside that list.
// Scoped API key configuration per agent
const agentPermissions = {
"agent-order-bot": {
allowedEndpoints: [
"GET /api/orders/:id",
"GET /api/orders/:id/status"
],
rateLimit: { requests: 20, windowSeconds: 60 },
maxChainDepth: 3
},
"agent-support-bot": {
allowedEndpoints: [
"GET /api/orders/:id",
"POST /api/tickets",
"GET /api/tickets/:id"
],
rateLimit: { requests: 10, windowSeconds: 60 },
maxChainDepth: 5
}
};
// Middleware: check agent scope before processing
function enforceAgentScope(req, res, next) {
const agentId = req.headers["x-agent-id"];
const permissions = agentPermissions[agentId];
if (!permissions) {
return res.status(403).json({ error: "Unknown agent" });
}
const route = `${req.method} ${req.route.path}`;
if (!permissions.allowedEndpoints.includes(route)) {
return res.status(403).json({
error: "Endpoint not in agent scope",
agent: agentId,
attempted: route
});
}
next();
}
To verify that an agent's JWT carries the correct scope before processing, inspect the token claims.
The /v1/jwt/decode endpoint decodes any JWT without needing the signing key, so you can
audit token contents during development and in your CI pipeline:
curl -s -X POST https://api.botoi.com/v1/jwt/decode \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZ2VudC1vcmRlci1ib3QiLCJzY29wZSI6Im9yZGVycy5yZWFkIiwiaWF0IjoxNzQ5NTY0ODAwLCJleHAiOjE3NDk1NjgwMDB9.signature"
}' Response:
{
"success": true,
"data": {
"header": {
"alg": "RS256",
"typ": "JWT"
},
"payload": {
"sub": "agent-order-bot",
"scope": "orders.read",
"iat": 1749564800,
"exp": 1749568000
}
}
}
The scope claim says orders.read. If this agent calls
POST /api/orders/:id/cancel, your middleware should reject the request before it reaches
your handler.
2. Tool misuse and privilege escalation: agents chaining API calls
Tool misuse logged 520 incidents in early reporting, making it the most common agentic threat. The pattern: an agent calls endpoint A, extracts data from the response, then uses that data to call endpoint B in a way the developer never anticipated.
Example: A Stripe integration agent has access to GET /api/customers/:id
and POST /api/refunds. The agent reads a customer's payment history, identifies the
highest-value transaction, and issues a refund to itself. Each individual call passes authorization.
The chain is the exploit.
Fix: per-agent rate limits and chain depth tracking
Standard rate limiting counts requests per IP or per API key. Agentic rate limiting adds two dimensions:
- Per-tool limits: Cap how many times a single agent can call a specific endpoint within a window
- Chain depth limits: Track how many sequential API calls an agent makes in a single session and cut it off at a defined threshold
| Rate limit type | What it catches | Who needs it |
|---|---|---|
| Per-IP | DDoS, credential stuffing | Every API |
| Per-API-key | Abusive individual consumers | Every API |
| Per-agent-per-tool | Agent calling one endpoint in a loop | APIs consumed by agents |
| Chain depth | Multi-step privilege escalation | APIs consumed by agents |
Require agents to send an X-Agent-Session header. Track the call count per session. When the
count exceeds your threshold, return a 429 with a clear error message.
3. Insufficient logging: no visibility into agent API calls
48.9% of organizations are blind to machine-to-machine traffic. When an agent exploits your API, you need to answer: which agent? Which endpoints? In what order? Over what time window? Standard access logs show IP addresses and timestamps. They don't show agent identity or call sequences.
The OWASP agentic list flags insufficient logging as a top risk because agent attacks look like authorized traffic. Every individual request passes auth. The exploit lives in the pattern across multiple requests.
Fix: require attribution headers and log call chains
Add three required headers for agent consumers:
X-Agent-ID: unique identifier for the agent (tied to its API key)X-Agent-Session: identifier for the current task or conversationUser-Agent: agent framework and version (e.g.,LangChain/0.3.1)
// Middleware: log every agent request with attribution
function agentAuditLog(req, res, next) {
const logEntry = {
timestamp: new Date().toISOString(),
agentId: req.headers["x-agent-id"] || "unknown",
apiKey: req.headers["x-api-key"]?.slice(-8) || "none",
method: req.method,
path: req.path,
sessionId: req.headers["x-agent-session"] || "none",
ip: req.ip,
userAgent: req.headers["user-agent"]
};
// Structured JSON log for your SIEM
console.log(JSON.stringify(logEntry));
// Track chain depth per session
const session = req.headers["x-agent-session"];
if (session) {
const depth = chainTracker.increment(session);
if (depth > MAX_CHAIN_DEPTH) {
return res.status(429).json({
error: "Agent chain depth exceeded",
maxDepth: MAX_CHAIN_DEPTH,
currentDepth: depth
});
}
}
next();
}
This middleware logs every request as structured JSON, which feeds into any SIEM or log aggregator.
It also enforces chain depth by tracking sequential calls per session. When you investigate an incident,
you can reconstruct the full chain by filtering on sessionId.
4. Insecure output handling: agents trusting API responses without validation
An agent calls your API, receives a JSON response, and passes it to the next step in its chain. If the response contains unexpected fields, wrong types, or injected content, the agent propagates the problem downstream. This is the agentic equivalent of OWASP API10 (unsafe consumption of APIs), amplified by the fact that agents process responses automatically with no human review.
Example: A competitor compromises a third-party pricing API. The agent fetches product
prices, receives a response with a manipulated price field set to 0.01, and places an order
at that price. No human ever saw the response.
Fix: validate every response against a JSON Schema
Start by generating a schema from a known-good response. The /v1/schema/json-to-jsonschema
endpoint produces a JSON Schema from any sample JSON:
curl -s -X POST https://api.botoi.com/v1/schema/json-to-jsonschema \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"json": {
"orderId": "ord_12345",
"status": "shipped",
"total": 49.99,
"items": [
{ "sku": "WIDGET-A", "quantity": 2 }
]
}
}' Response:
{
"success": true,
"data": {
"schema": {
"type": "object",
"properties": {
"orderId": { "type": "string" },
"status": { "type": "string" },
"total": { "type": "number" },
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"sku": { "type": "string" },
"quantity": { "type": "integer" }
}
}
}
}
}
}
}
Then validate every response your agent receives against that schema. The /v1/schema/validate
endpoint checks a JSON object against any JSON Schema and returns specific errors:
curl -s -X POST https://api.botoi.com/v1/schema/validate \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"schema": {
"type": "object",
"required": ["orderId", "status", "total"],
"properties": {
"orderId": { "type": "string" },
"status": { "type": "string", "enum": ["pending", "shipped", "delivered"] },
"total": { "type": "number", "minimum": 0 }
},
"additionalProperties": false
},
"data": {
"orderId": "ord_12345",
"status": "shipped",
"total": 49.99,
"internalNote": "rush order"
}
}' Response:
{
"success": true,
"data": {
"valid": false,
"errors": [
{
"path": "",
"message": "must NOT have additional properties: internalNote"
}
]
}
}
The validation caught internalNote, a field that doesn't belong in the response. If an API
starts returning unexpected fields, your agent stops processing instead of passing tainted data downstream.
Here's the full pattern using the Botoi Node.js SDK:
import Botoi from "botoi";
const botoi = new Botoi({ apiKey: process.env.BOTOI_API_KEY });
// Step 1: generate a schema from a known-good response
const schemaResult = await botoi.schema.jsonToJsonschema({
json: knownGoodResponse
});
const responseSchema = schemaResult.data.schema;
// Step 2: validate every agent-received response against that schema
async function validateAgentResponse(response) {
const validation = await botoi.schema.validate({
schema: responseSchema,
data: response
});
if (!validation.data.valid) {
console.error("Response failed validation:", validation.data.errors);
throw new Error("Untrusted response rejected by schema validation");
}
return response;
} 5. Supply chain vulnerabilities: compromised tool definitions
AI agents discover tools through MCP servers, OpenAPI specs, and tool manifests. If an attacker modifies a tool definition, the agent calls a different endpoint, sends data to a different server, or executes with different parameters than the developer intended.
Example: You use an open-source MCP server that defines 30 tools. An attacker submits
a pull request that changes one tool's API URL from api.stripe.com to
api.str1pe.com. The change passes code review because it's a single character. Your agent
now sends payment data to the attacker's server.
Fix: hash tool definitions and verify at runtime
Hash every tool definition at deploy time. Before your agent registers a tool at runtime, hash it again
and compare. The /v1/hash endpoint generates a SHA-256 hash of any string:
curl -s -X POST https://api.botoi.com/v1/hash \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"text": "{\"name\":\"get_order_status\",\"description\":\"Retrieve current order status by order ID\",\"parameters\":{\"orderId\":\"string\"}}",
"algorithm": "sha256"
}' Response:
{
"success": true,
"data": {
"hash": "a3f2b8c1d4e5f67890abcdef1234567890abcdef1234567890abcdef12345678",
"algorithm": "sha256"
}
} Here's the full integrity check workflow using the Botoi SDK:
import Botoi from "botoi";
import fs from "fs";
const botoi = new Botoi({ apiKey: process.env.BOTOI_API_KEY });
// Hash every tool definition at deploy time
const toolDefs = JSON.parse(fs.readFileSync("./mcp-tools.json", "utf-8"));
const hashes = {};
for (const tool of toolDefs) {
const result = await botoi.hash.sha256({
text: JSON.stringify(tool)
});
hashes[tool.name] = result.data.hash;
}
fs.writeFileSync("./tool-hashes.json", JSON.stringify(hashes, null, 2));
// At runtime, verify before registering any tool
async function verifyToolIntegrity(tool) {
const result = await botoi.hash.sha256({
text: JSON.stringify(tool)
});
const expected = hashes[tool.name];
if (result.data.hash !== expected) {
throw new Error(
`Tool "${tool.name}" failed integrity check. \n` +
`Expected: ${expected}\n` +
`Got: ${result.data.hash}`
);
}
} Run the hash generation step in your CI pipeline. Store the hashes file alongside your deployment artifact. At runtime, every tool gets verified before registration. A single changed character in any tool definition triggers a hard failure.
OWASP agentic top 10 vs API Security top 10: comparison
The two lists complement each other. Here's how the five agentic risks map to their closest API Security counterparts and what changes:
| Agentic risk | Closest API Security risk | What changes for agents |
|---|---|---|
| Excessive Agency | API5 Broken Function Auth | Agents discover all endpoints from specs; scope keys per agent |
| Tool Misuse | API4 Resource Consumption | Agents chain calls to escalate; add chain depth limits |
| Insufficient Logging | No direct equivalent | Agent calls look like authorized traffic; add attribution headers |
| Insecure Output | API10 Unsafe Consumption | Agents process responses without human review; add schema validation |
| Supply Chain | No direct equivalent | Compromised tool defs redirect agent traffic; add integrity hashes |
Ship checklist: five fixes for agentic API security
Each fix is independent. Pick one, ship it, move to the next.
| Fix | What to do | Botoi endpoint |
|---|---|---|
| Scoped API keys | One key per agent; allowlist endpoints per key | /v1/jwt/decode |
| Per-agent rate limits | Track per-tool and per-session chain depth | |
| Attribution headers | Require X-Agent-ID, X-Agent-Session; log structured JSON | |
| Response validation | Generate schema from good response; validate all agent responses | /v1/schema/validate, /v1/schema/json-to-jsonschema |
| Tool integrity | Hash tool defs at deploy; verify at runtime | /v1/hash |
What comes next
The full OWASP Top 10 for Agentic Applications lives at owasp.org. Cisco, Microsoft, and Google all announced agentic security initiatives at RSAC 2026, so expect tooling and standards to move fast through the rest of the year.
The five remaining risks on the list (Prompt Injection, Memory Poisoning, Cascading Failures, Data Leakage, and Inadequate Sandboxing) require fixes at the agent framework layer, not the API layer. If you run an agent framework, read the full OWASP document. If you run APIs, the five fixes above are your starting point.
Start with scoped API keys. That single change blocks the majority of excessive agency and tool misuse scenarios. Then add attribution headers so you can see what your agents are doing. The rest follows from visibility.
Frequently asked questions
- How does the OWASP Agentic Applications Top 10 differ from the OWASP API Security Top 10?
- The API Security Top 10 (2023) addresses risks from human consumers: broken authorization, authentication flaws, excessive data exposure. The Agentic Applications Top 10 (2026) addresses risks from autonomous AI agents that chain API calls, retain memory across sessions, and make decisions without human oversight. Both lists apply to APIs, but the agentic list targets machine-to-machine patterns the original never anticipated.
- What is excessive agency in agentic applications?
- Excessive agency occurs when an AI agent has access to API endpoints or actions beyond what its task requires. For example, a customer-support agent with access to billing, refund, and account deletion endpoints can chain those calls to escalate far beyond answering questions. The fix is scoped API keys that restrict each agent to the exact endpoints it needs.
- Do I need to rebuild my API for agentic security?
- No. You do not need to rebuild. The five fixes covered in this guide, scoped API keys, per-tool rate limits, request attribution headers, response schema validation, and tool definition integrity checks, are additions to your existing API. You can ship each one independently.
- Why is tool misuse the most common agentic application threat?
- Tool misuse and privilege escalation logged 520 incidents in early reporting because agents chain API calls in ways developers never intended. A single agent may call a read endpoint, parse the response, then call a write endpoint using data from the first call to escalate privileges. Most APIs have no mechanism to detect or block multi-step chains from a single agent session.
- How do I attribute API requests to specific AI agents?
- Add a required X-Agent-ID header to your API. Each agent gets a unique identifier tied to its scoped API key. Log both the API key and the agent ID on every request. This gives you a full audit trail of which agent called which endpoint, when, and in what sequence.
Try this API
JWT Decoder API — interactive playground and code examples
More guide posts
Start building with botoi
150+ API endpoints for lookup, text processing, image generation, and developer utilities. Free tier, no credit card.