PT-2026-133261

CVE-2026-62248

·

Publicado

2026-10-29

·

Atualizado

2026-10-29

Descrição por

CVSS 3.1
7.3
Alta
MétricasAV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H

Summary

JobWorkflowExecutor. exec inline python() is designed to safely execute inline Python expressions from YAML workflow script: steps using AST validation. The function claims to block dangerous operations by (a) checking all AST nodes against an allowlist, and (b) providing a builtins whitelist that omits import , exec, eval, and open.
The sandbox is broken. The module import allowlist (allowed modules) explicitly includes 'os', and the AST allowlist permits ast.Import, ast.ImportFrom, ast.Call, and ast.Attribute nodes. This means the following malicious workflow script: step passes all AST validation checks and executes without error.
Attack Scenario
Attacker creates or contributes a YAML workflow file (type: job) with a script: step containing import os; os.system(...). A user or CI pipeline with PRAISONAI ALLOW JOB WORKFLOWS=true executes the workflow via praisonai workflow run malicious.yaml. Arbitrary OS commands execute with the privileges of the calling process.
This is particularly dangerous in multi-tenant or CI environments where YAML workflows may originate from untrusted sources (e.g., downloaded templates, shared repositories, AI-generated workflows).

PoC

Complete instructions, including specific configuration details, to reproduce the vulnerability.

Impact

Root Cause — Lines 364–372:
pythonallowed modules = {'os', 'datetime', 'time', 'json', 'math', 're', 'collections', 'itertools'} if isinstance(node, ast.Import): for alias in node.names: if alias.name.split('.')[0] not in allowed modules: return {"ok": False, "error": f"Import of '{alias.name}' not allowed..."}
os is trusted because it is commonly used for path operations (os.path, os.getcwd). However, os.system(), os.popen(), os.execvp(), os.spawn*(), and os. exit() are all accessible once the module is imported, none of which are individually blocked.
The builtins restriction (blocking import ) is irrelevant because the code uses a real import statement processed by the Python bytecode compiler — not a import () call.
Proof-of-Concept validation (static — no remote network call made):
pythonimport ast
ALLOWED NODES = ( ast.Expression, ast.BoolOp, ast.BinOp, ast.UnaryOp, ast.Compare, ast.IfExp, ast.Constant, ast.Name, ast.Load, ast.Store, ast.Subscript, ast.List, ast.Tuple, ast.Dict, ast.Set, ast.And, ast.Or, ast.Not, ast.Eq, ast.NotEq, ast.Lt, ast.LtE, ast.Gt, ast.GtE, ast.In, ast.NotIn, ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod, ast.FloorDiv, ast.USub, ast.UAdd, ast.Call, ast.Attribute, ast.keyword, ast.Starred, ast.Module, ast.Assign, ast.Import, ast.ImportFrom, ast.alias, ) allowed modules = {'os', 'datetime', 'time', 'json', 'math', 're', 'collections', 'itertools'}
malicious = "import os result = os.system('id')" tree = ast.parse(malicious, mode="exec")
all pass = True for node in ast.walk(tree): if not isinstance(node, ALLOWED NODES): print(f"BLOCKED: {type(node). name }") all pass = False if isinstance(node, ast.Import): for alias in node.names: if alias.name.split('.')[0] not in allowed modules: print(f"IMPORT BLOCKED: {alias.name}") all pass = False
print("SANDBOX BYPASSED" if all pass else "sandbox holds")

Output: SANDBOX BYPASSED

Recommended Fix
Remove 'os' from allowed modules and replace it with only the safe submodule: 'os.path'. Then validate that the imported name is specifically os.path, not os:
python# BEFORE (vulnerable) allowed modules = {'os', 'datetime', 'time', 'json', 'math', 're', 'collections', 'itertools'}

AFTER (safe)

allowed modules = {'datetime', 'time', 'json', 'math', 're', 'collections', 'itertools', 'pathlib'}

If os.path is needed, handle it explicitly:

if isinstance(node, ast.ImportFrom): if node.module == 'os.path': pass # allow 'from os.path import join, exists' only elif node.module and node.module.split('.')[0] not in allowed modules: return {"ok": False, "error": f"Import of '{node.module}' not allowed."}
Additionally, block ast.Import of os entirely, and consider also removing re (which can be used for ReDoS/CPU exhaustion) and collections (which can be used to reach subclasses -style gadgets).
Explorabilidade
Correção
Impactos
Fornecedores
Produtos afetados
Identificadores relacionados
GHSA-26MH-57Q7-JFVR
Encontrou algum problema na descrição? Tem algo a acrescentar? Fique à vontade para nos escrever 👾