📋 What Is It?
Excessive Agency occurs when LLM-based systems are granted excessive permissions, autonomy, or functionality without appropriate controls, allowing them to perform high-impact actions without human oversight. This vulnerability is critical because it enables AI agents to cause significant damage through unrestricted access to sensitive operations.
LLM08
OWASP Rank
High
Impact
Severe
Potential Damage
⚠️ Common Exploits
- Unrestricted Function Calling: LLM can invoke any available function
- Excessive Permissions: Access to admin-level operations
- No Human-in-the-Loop: Critical actions without approval
- Unbounded Autonomy: LLM makes decisions independently
- Missing Guardrails: No constraints on action scope
🔴 Attack Flow
1. Attacker manipulates LLM via prompt injection
↓
2. LLM decides to perform privileged action
↓
3. No human approval required
↓
4. LLM executes destructive operation
↓
5. BREACH: Data deleted, money transferred, system compromised!
↓
2. LLM decides to perform privileged action
↓
3. No human approval required
↓
4. LLM executes destructive operation
↓
5. BREACH: Data deleted, money transferred, system compromised!
❌ Vulnerable Code
# Bad: LLM with unrestricted function access
class VulnerableAgent:
def __init__(self):
# VULNERABLE: All functions available to LLM!
self.available_functions = {
'delete_user': delete_user,
'transfer_money': transfer_money,
'grant_admin': grant_admin_access,
'delete_database': drop_all_tables,
'send_email_all': email_all_users
}
def execute(self, user_prompt):
# LLM decides which function to call
response = llm.function_call(
prompt=user_prompt,
functions=self.available_functions
)
# VULNERABLE: Direct execution without approval!
return response.function_result
# Bad: No limits on LLM autonomy
def autonomous_assistant(goal):
while not goal_achieved:
action = llm.decide_next_action()
execute_action(action) # Unconstrained!
✅ Secure Code
# Good: Restricted function access with human-in-the-loop
class SecureAgent:
def __init__(self):
# Safe, read-only functions
self.allowed_functions = {
'search_products': search_products,
'get_order_status': get_order_status,
'check_inventory': check_inventory
}
# Sensitive functions require approval
self.restricted_functions = {
'place_order': place_order,
'update_profile': update_user_profile
}
def execute(self, user_prompt, user_id):
response = llm.function_call(
prompt=user_prompt,
functions=self.allowed_functions
)
# Check if restricted function
if response.function in self.restricted_functions:
# Require human approval
approval = request_user_approval(
user_id,
response.function,
response.args
)
if not approval:
return "Action requires your approval. Please confirm."
# Execute with validation
return self.execute_with_limits(response)
# Good: Implement action constraints
class ConstrainedAgent:
def __init__(self):
self.max_actions_per_session = 10
self.action_count = 0
self.forbidden_actions = [
'delete', 'drop', 'grant_admin'
]
def execute_action(self, action):
# Check action count limit
if self.action_count >= self.max_actions_per_session:
raise Exception("Action limit exceeded")
# Check if action is forbidden
if any(forbidden in action.lower()
for forbidden in self.forbidden_actions):
raise PermissionError("Action not permitted")
# Log action
log_action(action, user_id, timestamp)
self.action_count += 1
return execute_safe(action)
# Good: Tiered permission model
class TieredAgent:
PERMISSION_TIERS = {
'read': ['search', 'get', 'view'],
'write': ['update', 'create'],
'admin': ['delete', 'grant'] # Never allow
}
def check_permission(self, action, user_role):
if user_role == 'basic':
allowed = self.PERMISSION_TIERS['read']
elif user_role == 'premium':
allowed = (self.PERMISSION_TIERS['read'] +
self.PERMISSION_TIERS['write'])
else:
allowed = self.PERMISSION_TIERS['read']
return any(a in action.lower() for a in allowed)
✓ Prevention Checklist
- Implement human-in-the-loop for sensitive actions
- Use principle of least privilege
- Restrict LLM to read-only operations when possible
- Require explicit user confirmation for state changes
- Implement action rate limiting
- Use tiered permission models
- Log all LLM-initiated actions
- Set maximum autonomy boundaries
- Implement circuit breakers for failures
- Regular audit of granted permissions
🔍 Detection & Tools
Control Frameworks:
LangChain Agent Tools
AutoGPT Constraints
BabyAGI Limiters
Semantic Kernel
Guardrails AI
Monitoring Tools:
LangSmith
Weights & Biases
MLflow
Arize AI
How to Test:
- Test LLM with privilege escalation prompts
- Verify human approval requirements
- Check permission boundaries enforcement
- Test action rate limiting
- Audit available function access
🌍 Real-World Examples
- AutoGPT Incidents (2023): Autonomous agents made unintended API calls costing thousands in credits
- AI Email Assistant (2023): Sent emails to wrong recipients without user confirmation
- Trading Bot Gone Wrong: LLM-based trading system executed unauthorized high-value trades
- Database Agent: Autonomous SQL agent accidentally deleted production data
- Social Media Bot: LLM agent posted inappropriate content without moderation
📌 Quick Tips
- DO NOT grant admin-level access
- DO NOT allow unrestricted autonomy
- DO NOT skip human approval
- DO implement least privilege
- DO require confirmation for changes
- DO log all actions
📜 Compliance
Related Standards:
- NIST AI RMF - Autonomy Controls
- ISO 27001 A.9.2 (Access Control)
- SOC 2 CC6.1, CC6.3
- GDPR Art. 22 - Automated Decision-Making
- CWE-269 Improper Privilege Management