PraisonAI recipe workflow policy can be bypassed by declaring and YAML-approving dangerous tools outside TEMPLATE.yaml
Date: 2026-06
Affected: pip/praisonai
Attack vector: rce
Category: vulnerability-disclosure
Severity: High
CWE: CWE-78
CWE-863
CWE-94
CVSS: 7.8 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

## Summary PraisonAI recipe execution has a dangerous-tool policy that is supposed to block default-denied tools unless the caller explicitly passes `allow_dangerous_tools=True`. That policy only checks tools declared in `TEMPLATE.yaml` `requires.tools`. For steps-based recipes, the actual execution path loads `workflow.yaml` with `YAMLWorkflowParser`. That parser resolves agent-level `tools:` declarations and preserves top-level `approve:`. `Workflow.start()` then installs those YAML-approved tools into the approval context. As a result, an untrusted recipe can omit `execute_command` from `TEMPLATE.yaml requires.tools`, declare it in `workflow.yaml agents.*.tools`, and add top-level `approve: [execute_command]`. The caller did not set `allow_dangerous_tools=True`, but the recipe policy allows the recipe and the workflow approval path self-approves the critical shell tool. The local PoV uses a harmless `printf` canary and explicitly unsets `PRAISONAI_AUTO_APPROVE`. ## Technical Details `recipe.run()` checks the recipe policy unless `options["allow_dangerous_tools"]` is true. `_check_tool_policy()` gets the required tool list from `recipe_config.get_required_tools()`, which is backed by `TEMPLATE.yaml` `requires.tools`. The steps workflow execution path is separate: 1. `_execute_steps_workflow()` parses the workflow file with `YAMLWorkflowParser`. 2. `YAMLWorkflowParser` resolves `agents.*.tools`. 3. The same parser reads top-level `approve:` and stores it on `workflow


Mitigations:

Architectural layers (MAESTRO):