GHSA-9gm9-c8mq-vq7m
PraisonAI: OS Command Injection in MCPHandler.parse_mcp_command()
Packages
Details
As written in the advisory (Markdown source, shown as plain text).
### Summary
The `--mcp` CLI argument is passed directly to `shlex.split()` and forwarded through the call chain to `anyio.open_process()` with no validation, allowlist check, or sanitization at any hop, allowing arbitrary OS command execution as the process user.
### Details
`cli/features/mcp.py:61` (source) -> `praisonaiagents/mcp/mcp.py:345` (hop) -> `mcp/client/stdio/__init__.py:253` (sink)
```python
# source
parts = shlex.split(command)
# hop
cmd, args, env = self.parse_mcp_command(command, env_vars)
self.server_params = StdioServerParameters(command=cmd, args=arguments)
# sink
process = await anyio.open_process([command, *args])
```
Fixed in commit `47bff65413beaa3c21bf633c1fae4e684348368c` (v4.5.69) by introducing a command allowlist:
```python
ALLOWED_COMMANDS = {"npx", "uvx", "node", "python"}
if cmd not in ALLOWED_COMMANDS:
raise ValueError(f"Disallowed command: {cmd}")
```
### PoC
```python
# tested on: praisonai==4.5.48
# install: pip install praisonai==4.5.48
# run: praisonai --mcp "bash -c 'id > /tmp/pwned'"
# verify: cat /tmp/pwned
# expected output: uid=1000(...) gid=1000(...) groups=1000(...)
```
### Impact
Any deployment where the `--mcp` argument is influenced by untrusted input is exposed to full OS command execution as the process user. No authentication is required.
References
External links from the advisory. They lead to third-party sites.