OWASP Top 10 for Agentic AI Applications
Source: mortalapps.com- The OWASP Top 10 for Agentic AI is a specialized security framework addressing vulnerabilities unique to autonomous systems with tool-use capabilities.
- It solves the problem of securing agents that move beyond passive text generation into active environment manipulation and multi-step reasoning.
- Production significance lies in preventing unauthorized tool execution, data exfiltration, and recursive resource exhaustion in autonomous loops.
- Implementing this framework results in a 'Secure Agent Perimeter' that enforces least privilege and validates every transition in an agent's state machine.
- A key tradeoff is the latency penalty introduced by secondary security LLMs and runtime validation layers.
Why This Matters
The transition from Large Language Models (LLMs) to Agentic AI introduces a fundamental shift in the security threat model. Traditional LLM security focuses on input/output filtering (prompt injection and PII leakage). However, Agentic AI possesses 'agency' - the ability to use tools, maintain long-term memory, and execute multi-step plans without human intervention. This agency transforms a text-based vulnerability into a system-level exploit. If an agent is compromised via indirect prompt injection, it does not just return a malicious string; it may delete a production database, exfiltrate customer data via an MCP server, or spin up unauthorized cloud resources.
This framework was developed because standard web application security (OWASP Top 10) and LLM security (OWASP Top 10 for LLM) fail to cover the recursive nature of agent loops and the supply chain risks of third-party tool ecosystems like the Model Context Protocol (MCP). In production, ignoring these agent-specific vulnerabilities leads to 'excessive agency,' where an agent has more permissions than it requires to fulfill its goal, creating a massive attack surface. Engineers must use this framework to design 'defense-in-depth' architectures where the orchestrator, the tools, and the memory systems are isolated and audited. It is the difference between a chatbot that says something offensive and an agent that executes a destructive rm -rf command on a mounted volume because it was 'convinced' to do so by a malicious email it was tasked to summarize.
Core Concepts
To secure agentic systems, engineers must master the following security-specific concepts:
- Indirect Prompt Injection: A vulnerability where an agent processes untrusted data (e.g., a website, an email, or a document) that contains hidden instructions designed to hijack the agent's goal.
- Excessive Agency: Granting an agent more tools, permissions, or data access than is strictly necessary for its defined task, violating the principle of least privilege.
- Recursive Loop Budget: A security constraint that limits the number of iterations or tool calls an agent can perform in a single session to prevent resource exhaustion (ASI09).
- Tool Sandboxing: The practice of executing agent-triggered code or system commands in an isolated environment (e.g., Docker, gVisor, or E2B) to prevent host compromise.
- Human-in-the-Loop (HITL): A governance pattern where high-risk actions (e.g., financial transfers, data deletion) require explicit human approval before execution.
- Agent Identity: The cryptographic or token-based representation of an agent's permissions, distinct from the user's identity, used to track and limit tool access.
| Concept | Security Role | Production Impact |
|---|---|---|
| Orchestrator Isolation | Prevents prompt leakage | Limits blast radius of a hijacked session |
| Tool Guardrails | Validates tool arguments | Prevents SQL injection or path traversal via agent |
| State Persistence | Audits agent history | Enables forensic analysis after a security breach |
How It Works
The security lifecycle of an agentic application involves four distinct phases: Input Validation, Reasoning Guardrails, Execution Sandboxing, and Output Sanitization.
1. Input Validation and Context Scrubbing
Before the agent processes a request, the system must distinguish between 'System Instructions' (trusted) and 'User/External Data' (untrusted). In agentic RAG or email-processing agents, external data is often the vector for Indirect Prompt Injection. The system scrubs this data for known injection patterns and uses delimiters to isolate untrusted content from the core agent instructions.
2. Reasoning and Plan Validation
Once the agent generates a plan (e.g., using a ReAct or Plan-and-Execute pattern), the orchestrator intercepts the plan before any tool is called. A secondary, highly restricted 'Guardrail LLM' or a deterministic policy engine (like OPA) evaluates the plan against a set of safety rules. If the plan involves high-risk tools or violates the 'Recursive Loop Budget,' the process is halted or escalated for human approval.
3. Sandboxed Tool Execution
When a tool call is authorized, it is executed in a restricted environment. For example, if an agent uses a 'Python Interpreter' tool, the code runs in a MicroVM or a container with no network access (unless explicitly required) and limited CPU/RAM. The tool's output is captured and validated to ensure it does not contain malicious payloads that could exploit the agent's reasoning in the next turn of the loop.
4. Failure Paths and Recovery
If a security violation is detected (e.g., an agent attempts to access a file outside its scope), the system must fail safely. This involves terminating the agent session, logging the event via OpenTelemetry GenAI spans, and notifying the security operations center (SOC). The system should never allow the agent to 'retry' its way out of a security block without external intervention.
Architecture
The architecture of a secure agentic system is defined by a 'Security Proxy' pattern. The system consists of five primary components: (1) The Orchestrator, which manages the agent's state and reasoning; (2) The Policy Engine, which stores RBAC and tool-use policies; (3) The Tool Sandbox, an isolated execution environment for MCP servers or local functions; (4) The Audit Store, a tamper-proof log of all prompts, reasoning steps, and tool outputs; and (5) The Human-in-the-Loop (HITL) Gateway, which intercepts high-risk actions.
Execution starts when a user request enters the Orchestrator. The Orchestrator queries the Policy Engine to determine the agent's scope. As the agent generates tool calls, these calls are routed through the Security Proxy, which validates arguments against the Policy Engine. The calls then execute in the Tool Sandbox. Data flows back from the Sandbox to the Orchestrator, but only after being sanitized. All transitions are recorded in the Audit Store. The flow ends when the agent produces a final response or is terminated by a policy violation.
ASI01: Agent Goal Hijacking
Goal hijacking occurs when an agent's primary objective is overridden by malicious instructions embedded in external data. Unlike direct prompt injection, this often happens 'indirectly' when an agent reads a document or website.
Mitigation Strategy: Implement 'Dual LLM' architectures where one model processes the untrusted data and extracts only relevant facts, while the primary agent model uses those facts within a strictly defined system prompt. Use XML-style delimiters (e.g., <untrusted_data>...</untrusted_data>) and instruct the model to ignore any commands within those tags.
ASI02: Tool Misuse and Recursive Loops
Agents can be manipulated into calling tools with malicious arguments (e.g., a file-read tool called with /etc/passwd) or entering infinite loops that consume excessive tokens and compute.
Mitigation Strategy: Use Pydantic or JSON Schema to strictly type-validate all tool arguments. Implement a max_iterations counter in the orchestrator. For MCP-based tools, use ttlMs to expire long-running requests and enforce rate limits at the tool-server level.
ASI03: Agent Identity and Privilege Abuse
In many implementations, agents run with the same privileges as the application's service account. If the agent is hijacked, the attacker gains full access to the backend infrastructure.
Mitigation Strategy: Assign each agent a unique identity and use OAuth 2.1 scopes to limit what each agent can do. If an agent only needs to read from a specific S3 bucket, its identity should have no other permissions. Use 'On-Behalf-Of' (OBO) flows to ensure the agent cannot exceed the permissions of the user who triggered it.
ASI04: Supply Chain Compromise
Agentic systems rely on third-party tools, MCP servers, and skill libraries. A compromised tool can return malicious data that exploits the agent's reasoning or exfiltrates the system prompt.
Mitigation Strategy: Pin tool versions and use subresource integrity (SRI) where applicable. Audit third-party MCP servers before integration. Implement a 'Tool Registry' that only allows execution of pre-approved, scanned functions.
ASI05: Unexpected Code Execution
Agents with access to code interpreters (e.g., Python, Bash) are high-risk targets. Attackers can use the agent to run arbitrary code on the host system.
Mitigation Strategy: Always use a hardened sandbox like E2B, AWS Lambda, or a gVisor-protected container. Disable network access for code-executing tools unless strictly necessary. Monitor system calls within the sandbox for anomalous behavior (e.g., attempts to access /dev/ or /proc/).
ASI06: Excessive Agency
Excessive agency occurs when an agent is given access to tools it doesn't need 'just in case' or when it is allowed to perform destructive actions without confirmation.
Mitigation Strategy: Apply the Principle of Least Agency. Break complex agents into smaller, specialized sub-agents with limited toolsets. For example, a 'Search Agent' should not have access to the 'Email Send' tool. Use conditional routing to only expose tools when specific state conditions are met.
ASI07: System Prompt Leakage
Attackers can use 'jailbreak' techniques to force the agent to reveal its system prompt, which may contain sensitive business logic, internal API endpoints, or security instructions.
Mitigation Strategy: Monitor for 'canary tokens' in agent outputs - unique strings that should never be revealed. Use output filtering to block responses that contain phrases like 'You are an AI assistant' or other common system prompt starters.
ASI08: Insecure Output Handling
If an agent's output is rendered directly in a UI or passed to another system without sanitization, it can lead to Cross-Site Scripting (XSS) or Command Injection in downstream systems.
Mitigation Strategy: Treat agent output as untrusted user input. Sanitize all Markdown and HTML before rendering. If the agent generates code for a developer, ensure the code is clearly marked and requires manual review before execution.
ASI09: Resource Exhaustion
Malicious inputs can trigger 'token-heavy' reasoning paths or recursive tool calls designed to deplete the organization's LLM budget or crash the orchestrator.
Mitigation Strategy: Implement per-user and per-agent token quotas. Use 'Time-to-First-Token' (TTFT) and 'Total Request Time' timeouts. Monitor for 'stuck' agents that repeat the same reasoning steps without progressing toward a goal.
ASI10: Lack of Human-in-the-Loop (HITL)
Fully autonomous agents performing high-stakes actions without a 'kill switch' or approval step represent a significant governance risk.
Mitigation Strategy: Define a 'High-Risk Action' registry. Any tool call in this registry must trigger an interrupt in the state machine, persisting the state and notifying a human operator for approval via a dashboard or Slack integration.
Code Example
import os
from pydantic import BaseModel, Field, validator
from typing import List, Optional
import logging
# Configure secure logging for audit trails
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("agent_security")
class ToolArguments(BaseModel):
"""Schema for a file-read tool with path validation (ASI02)"""
file_path: str = Field(..., description="Path to the file to read")
@validator('file_path')
def prevent_path_traversal(cls, v):
# Block attempts to access sensitive directories
forbidden_paths = ['/etc', '/var', '/root', '..']
if any(p in v for p in forbidden_paths):
raise ValueError("Unauthorized path access attempt detected.")
return v
class AgentSession:
def __init__(self, max_loops: int = 5):
self.loop_count = 0
self.max_loops = max_loops
self.session_id = os.urandom(8).hex()
def execute_tool(self, tool_name: str, args: dict):
"""Executes a tool with recursive loop protection (ASI09)"""
self.loop_count += 1
if self.loop_count > self.max_loops:
logger.error(f"Session {self.session_id}: Recursive loop budget exceeded.")
return {"error": "Resource limit reached. Terminating session."}
# Validate arguments against schema
try:
validated_args = ToolArguments(**args)
logger.info(f"Session {self.session_id}: Executing {tool_name} with {validated_args}")
# Logic for actual tool execution would go here
return {"status": "success", "data": "File content..."}
except Exception as e:
logger.warning(f"Session {self.session_id}: Security violation - {str(e)}")
return {"error": "Security policy violation."}
# Usage
session = AgentSession(max_loops=3)
# Simulate a malicious tool call
result = session.execute_tool("read_file", {"file_path": "../../etc/passwd"})
print(result) # Output: {'error': 'Security policy violation.'}
{'error': 'Security policy violation.'}
def process_agent_action(action: str, is_high_risk: bool):
"""
Intercepts high-risk actions for human approval (ASI10).
In a real system, this would use a state machine like LangGraph.
"""
if is_high_risk:
# Persist state to DB and wait for human signal
save_state_for_approval(action)
return {"status": "PENDING_APPROVAL", "message": "Action requires human review."}
return execute_action_immediately(action)
def save_state_for_approval(action):
# Mock persistence logic
print(f"[SECURITY] Action '{action}' flagged. Waiting for human approval...")
def execute_action_immediately(action):
return {"status": "COMPLETED", "action": action}
# Example: Financial transfer is high risk
response = process_agent_action("transfer_funds_1000", is_high_risk=True)
print(response)
[SECURITY] Action 'transfer_funds_1000' flagged. Waiting for human approval...
{'status': 'PENDING_APPROVAL', 'message': 'Action requires human review.'}