{"id":"GHSA-693f-pf34-72c5","summary":"PraisonAI Has Path Traversal in FileTools","details":"### Executive Summary:\nThe path validation has a critical logic bug: it checks for `..` AFTER `normpath()` has already collapsed all `..` sequences. This makes the check completely useless and allows trivial path traversal to any file on the system.\nThe path validation function also does not resolve the symlink wich could potentially cause path traversal.\n\n### Details:\n`_validate_path()` calls `os.path.normpath()` first, which collapses `..` sequences, then checks for `'..'` in normalized. Since `..` is already collapsed, the check always passes.\n\n**Vulnerable File:**\n`src/praisonai-agents/praisonaiagents/tools/file_tools.py`\n\n**Lines:**\n42-49\n\n```python\nclass FileTools:\n    \"\"\"Tools for file operations including read, write, list, and information.\"\"\"\n    \n    @staticmethod\n    def _validate_path(filepath: str) -\u003e str:\n        # Normalize the path\n        normalized = os.path.normpath(filepath)\n        absolute = os.path.abspath(normalized)\n        \n        # Check for path traversal attempts (.. after normalization)\n        # We check the original input for '..' to catch traversal attempts\n        if '..' in normalized:\n            raise ValueError(f\"Path traversal detected: {filepath}\")\n        \n        return absolute\n```\n\n**Severity:** CRITICAL\n\n**CVSS v3.1:** 9.2 (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N\n\n**CWE:** CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')\n\n### Proof of concept (PoC)\n\n**Prerequisites:**\n- Ability to specify a file path can call file operations\n\n**Steps to reproduce:**\npoc.py\n```python\nfrom praisonaiagents.tools.file_tools import FileTools\n\nprint(FileTools._validate_path('/tmp/../etc/passwd'))\n# Returns: /etc/passwd\n\nprint(FileTools.read_file('/tmp/../etc/passwd'))\n# Returns: content of /etc/passwd\n```\n\n**Why this works:**\n```python\n# Current vulnerable code:\nnormalized = os.path.normpath(filepath)  # Collapses .. HERE\nabsolute = os.path.abspath(normalized)\nif '..' in normalized:  # Check AFTER collapse - ALWAYS FALSE!\n    raise ValueError(...)\n```\n\n### Impact:\n- **Complete bypass** of path traversal protection\n- Access to ANY file on the system with path from any starting directory\n- Read sensitive files: `/etc/passwd`, `/etc/shadow`, `~/.ssh/id_rsa`\n- Write arbitrary files if combined with write operations\n- Affect file operations `read_file`, `write_file`, `list_files`, `get_file_info`, `copy_file`, `move_file`, `delete_file`, `download_file`\n\n\n### Additional Notes:\n- **Fix:** Check for `'..' in filepath` BEFORE calling `normpath()`, not after\n- `_validate_path` uses `os.path.normpath` and `os.path.abspath`, which don't resolve symlinks, making it vulnerable to path traversal via symlink if attacker can control the symlink.","aliases":["CVE-2026-35615"],"modified":"2026-04-07T22:21:23.020692Z","published":"2026-04-06T23:09:28Z","database_specific":{"nvd_published_at":"2026-04-07T17:16:35Z","cwe_ids":["CWE-22"],"github_reviewed":true,"github_reviewed_at":"2026-04-06T23:09:28Z","severity":"CRITICAL"},"references":[{"type":"WEB","url":"https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-693f-pf34-72c5"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-35615"},{"type":"PACKAGE","url":"https://github.com/MervinPraison/PraisonAI"},{"type":"WEB","url":"https://github.com/MervinPraison/PraisonAI/releases/tag/v4.5.113"}],"affected":[{"package":{"name":"praisonai","ecosystem":"PyPI","purl":"pkg:pypi/praisonai"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.5.113"}]}],"versions":["0.0.1","0.0.10","0.0.11","0.0.12","0.0.13","0.0.14","0.0.15","0.0.16","0.0.17","0.0.18","0.0.19","0.0.2","0.0.20","0.0.21","0.0.22","0.0.23","0.0.24","0.0.25","0.0.26","0.0.27","0.0.28","0.0.29","0.0.3","0.0.30","0.0.31","0.0.32","0.0.33","0.0.34","0.0.35","0.0.36","0.0.37","0.0.38","0.0.39","0.0.4","0.0.40","0.0.41","0.0.42","0.0.43","0.0.44","0.0.45","0.0.46","0.0.47","0.0.48","0.0.49","0.0.5","0.0.50","0.0.52","0.0.53","0.0.54","0.0.55","0.0.56","0.0.57","0.0.58","0.0.59","0.0.59rc11","0.0.59rc2","0.0.59rc3","0.0.59rc5","0.0.59rc6","0.0.59rc7","0.0.59rc8","0.0.59rc9","0.0.6","0.0.61","0.0.64","0.0.65","0.0.66","0.0.67","0.0.68","0.0.69","0.0.7","0.0.70","0.0.71","0.0.72","0.0.73","0.0.74","0.0.8","0.0.9","0.1.0","0.1.1","0.1.10","0.1.2","0.1.3","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.9","1.0.0","1.0.1","1.0.10","1.0.11","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.0.8","1.0.9"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-693f-pf34-72c5/GHSA-693f-pf34-72c5.json","last_known_affected_version_range":"\u003c= 1.5.112"}}],"schema_version":"1.7.5","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N"}]}