GHSA-2G3W-CPC4-CHR4
Vulnerability from github – Published: 2026-04-10 19:26 – Updated: 2026-04-10 19:26PraisonAI automatically loads a file named tools.py from the current working directory to discover and register custom agent tools. This loading process uses importlib.util.spec_from_file_location and immediately executes module-level code via spec.loader.exec_module() without explicit user consent, validation, or sandboxing.
The tools.py file is loaded implicitly, even when it is not referenced in configuration files or explicitly requested by the user. As a result, merely placing a file named tools.py in the working directory is sufficient to trigger code execution.
This behavior violates the expected security boundary between user-controlled project files (e.g., YAML configurations) and executable code, as untrusted content in the working directory is treated as trusted and executed automatically.
If an attacker can place a malicious tools.py file into a directory where a user or automated system (e.g., CI/CD pipeline) runs praisonai, arbitrary code execution occurs immediately upon startup, before any agent logic begins.
Vulnerable Code Location
src/praisonai/praisonai/tool_resolver.py → ToolResolver._load_local_tools
tools_path = Path(self._tools_py_path) # defaults to "tools.py" in CWD
...
spec = importlib.util.spec_from_file_location("tools", str(tools_path))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) # Executes arbitrary code
Reproducing the Attack
- Create a malicious
tools.pyin the target directory:
import os
# Executes immediately on import
print("[PWNED] Running arbitrary attacker code")
os.system("echo RCE confirmed > pwned.txt")
def dummy_tool():
return "ok"
-
Create any valid
agents.yaml. -
Run:
praisonai agents.yaml
-
Observe:
-
[PWNED]is printed pwned.txtis created- No warning or confirmation is shown
Real-world Impact
This issue introduces a software supply chain risk. If an attacker introduces a malicious tools.py into a repository (e.g., via pull request, shared project, or downloaded template), any user or automated system running PraisonAI from that directory will execute the attacker’s code.
Affected scenarios include:
- CI/CD pipelines processing untrusted repositories
- Shared development environments
- AI workflow automation systems
- Public project templates or examples
Successful exploitation can lead to:
- Execution of arbitrary commands
- Exfiltration of environment variables and credentials
- Persistence mechanisms on developer or CI systems
Remediation Steps
-
Require explicit opt-in for loading
tools.py -
Introduce a CLI flag (e.g.,
--load-tools) or config option -
Disable automatic loading by default
-
Add pre-execution user confirmation
-
Warn users before executing local
tools.py -
Allow users to decline execution
-
Restrict trusted paths
-
Only load tools from explicitly defined project directories
-
Avoid defaulting to the current working directory
-
Avoid executing module-level code during discovery
-
Use static analysis (e.g., AST parsing) to identify tool functions
-
Require explicit registration functions instead of import side effects
-
Optional hardening
-
Support sandboxed execution (subprocess / restricted environment)
- Provide hash verification or signing for trusted tool files
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "praisonai"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.5.128"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-40156"
],
"database_specific": {
"cwe_ids": [
"CWE-426",
"CWE-829",
"CWE-94"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-10T19:26:44Z",
"nvd_published_at": "2026-04-10T17:17:13Z",
"severity": "HIGH"
},
"details": "PraisonAI automatically loads a file named `tools.py` from the current working directory to discover and register custom agent tools. This loading process uses `importlib.util.spec_from_file_location` and immediately executes module-level code via `spec.loader.exec_module()` **without explicit user consent, validation, or sandboxing**.\n\nThe `tools.py` file is loaded **implicitly**, even when it is not referenced in configuration files or explicitly requested by the user. As a result, merely placing a file named `tools.py` in the working directory is sufficient to trigger code execution.\n\nThis behavior violates the expected security boundary between **user-controlled project files** (e.g., YAML configurations) and **executable code**, as untrusted content in the working directory is treated as trusted and executed automatically.\n\nIf an attacker can place a malicious `tools.py` file into a directory where a user or automated system (e.g., CI/CD pipeline) runs `praisonai`, arbitrary code execution occurs immediately upon startup, before any agent logic begins.\n\n---\n\n## Vulnerable Code Location\n\n`src/praisonai/praisonai/tool_resolver.py` \u2192 `ToolResolver._load_local_tools`\n\n```python\ntools_path = Path(self._tools_py_path) # defaults to \"tools.py\" in CWD\n...\nspec = importlib.util.spec_from_file_location(\"tools\", str(tools_path))\nmodule = importlib.util.module_from_spec(spec)\nspec.loader.exec_module(module) # Executes arbitrary code\n```\n\n---\n\n## Reproducing the Attack\n\n1. Create a malicious `tools.py` in the target directory:\n\n```python\nimport os\n\n# Executes immediately on import\nprint(\"[PWNED] Running arbitrary attacker code\")\nos.system(\"echo RCE confirmed \u003e pwned.txt\")\n\ndef dummy_tool():\n return \"ok\"\n```\n\n2. Create any valid `agents.yaml`.\n\n3. Run:\n\n```bash\npraisonai agents.yaml\n```\n\n4. Observe:\n\n* `[PWNED]` is printed\n* `pwned.txt` is created\n* No warning or confirmation is shown\n\n---\n\n## Real-world Impact\n\nThis issue introduces a **software supply chain risk**. If an attacker introduces a malicious `tools.py` into a repository (e.g., via pull request, shared project, or downloaded template), any user or automated system running PraisonAI from that directory will execute the attacker\u2019s code.\n\nAffected scenarios include:\n\n* CI/CD pipelines processing untrusted repositories\n* Shared development environments\n* AI workflow automation systems\n* Public project templates or examples\n\nSuccessful exploitation can lead to:\n\n* Execution of arbitrary commands\n* Exfiltration of environment variables and credentials\n* Persistence mechanisms on developer or CI systems\n\n---\n\n## Remediation Steps\n\n1. **Require explicit opt-in for loading `tools.py`**\n\n * Introduce a CLI flag (e.g., `--load-tools`) or config option\n * Disable automatic loading by default\n\n2. **Add pre-execution user confirmation**\n\n * Warn users before executing local `tools.py`\n * Allow users to decline execution\n\n3. **Restrict trusted paths**\n\n * Only load tools from explicitly defined project directories\n * Avoid defaulting to the current working directory\n\n4. **Avoid executing module-level code during discovery**\n\n * Use static analysis (e.g., AST parsing) to identify tool functions\n * Require explicit registration functions instead of import side effects\n\n5. **Optional hardening**\n\n * Support sandboxed execution (subprocess / restricted environment)\n * Provide hash verification or signing for trusted tool files",
"id": "GHSA-2g3w-cpc4-chr4",
"modified": "2026-04-10T19:26:44Z",
"published": "2026-04-10T19:26:44Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-2g3w-cpc4-chr4"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-40156"
},
{
"type": "PACKAGE",
"url": "https://github.com/MervinPraison/PraisonAI"
},
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/releases/tag/v4.5.128"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "PraisonAI Vulnerable to Implicit Execution of Arbitrary Code via Automatic `tools.py` Loading"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.