# AVideo has an incomplete fix of CVE-2026-33482: sanitizeFFmpegCommand still allows a single '&' (background operator), giving OS command execution at the same execAsync sh -c sink

AVideo's sanitizeFFmpegCommand fix for CVE-2026-33482 still permits a bare '&', letting an attacker with a valid encrypted payload run OS commands via the execAsync sh -c sink.

- Payout: Research
- Severity: high
- Program: AVideo
- Found by: anir0y
- Disclosed: 2026-06-23
- CVE: CVE-2026-55173
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-wc3f-xc32-435f
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-wc3f-xc32-435f
- Tags: area:web domain:web impact:rce kind:research platform:ghsa sev:high tech:php technique:incomplete-fix technique:source-review vuln:command-injection vuln:rce

**Target:** PHP standalone encoder API endpoint (ffmpeg.json.php) and execAsync sh -c sink
**Root cause:** sanitizeFFmpegCommand strips '&&' and a denylist char class lacking '&', so a single '&' survives and acts as a command separator inside the inner sh -c "..." wrapper built by execAsync.
**Steps:**
1. Read HEAD sanitizeFFmpegCommand in plugin/API/standAlone/functions.php: str_replace('&&',''), regex stripping '&' only before '>', and char class `[;|`<>$()\n\r{}]` with no '&'.
2. Craft payload `ffmpeg -i input.mp4 & touch /tmp/avideo_amp_rce_proof & echo done out.mp4`; it passes the prefix gate and sanitizer unchanged.
3. execAsync wraps it as `nohup sh -c "$command & echo \$! > /tmp/$keyword.pid" > /dev/null 2>&1 &` after addcslashes escaping only `"`.
4. Inner sh -c interprets the bare `&` as a separator and executes the injected `touch` (or `curl`, `nc`, etc.).
5. Deliver via `_decryptString(getInput('codeToExecEncrypted'))` at ffmpeg.json.php:418.
**How found:** Reviewed the patch for CVE-2026-33482 and noticed the denylist added `$(){}` and stripped only the doubled '&&', leaving the single '&' background operator unhandled at the same sh -c sink; verified with a byte-faithful PHP harness copying the sanitizer and execAsync wrapper.
**Exploitation:** Attacker supplies a valid encrypted codeToExecEncrypted payload to the standalone encoder endpoint; the decrypted ffmpeg command containing a single '&' passes sanitization and is interpolated into an inner sh -c, so the trailing injected command runs as the web server user on the encoder host. Multiple '&'-separated commands can be chained (download + execute); '>' redirects are blocked but command execution is not.
**Escalation:** Chaining multiple '&'-separated commands allows download-and-execute staging on the encoder server.
**Insight:** When auditing a fix for command injection, enumerate every shell metacharacter the sanitizer still permits at the sink — a denylist that patches one operator ('&&') while leaving its single form ('&') is a recurring incomplete-fix pattern; test each separator individually against the actual sh -c wrapper.

## Proof of concept (copied exactly from the original report)

**Ampersand bypass PoC harness output**

```
attacker input : ffmpeg -i input.mp4 & touch /tmp/avideo_amp_rce_proof & echo done out.mp4
after sanitize : ffmpeg -i input.mp4 & touch /tmp/avideo_amp_rce_proof & echo done out.mp4
ampersand survived : YES   passes prefix : YES
final sh -c string:
  nohup sh -c "ffmpeg -i input.mp4 & touch /tmp/avideo_amp_rce_proof & echo $! > /tmp/testkw.pid" > /dev/null 2>&1 &
>> injected touch executed: YES (/tmp/avideo_amp_rce_proof)
```

