
Advisory e prova di concetto per l'iniezione di comandi del sistema operativo in un helper MCP per ffmpeg, con analisi delle cause profonde, indicazioni per i rilevatori e mitigazioni per un pacchetto npm non corretto.
runFFmpegCommand passa una stringa costruita dai parametri dello strumento MCP a
spawn(…, { shell: true }), quindi i metacaratteri della shell in options, format,
codec, pixelFormat o extraOptions vengono eseguiti sull'host che esegue il server.
⚠ Non esiste una versione corretta
Al 2026-08-22 l'ultima release npm è la 0.2.1, che è la versione interessata, e il sink è ancora presente sul branch predefinito del repository. Non c'è nulla a cui aggiornare. Vedi Mitigazione per ciò che gli utenti possono fare nel frattempo.
| CVE | CVE-2026-52617 |
| CWE | CWE-78 (Neutralizzazione impropria di elementi speciali usati in un comando OS) |
| Pacchetto | @sworddut/mcp-ffmpeg-helper (npm) |
| Interessate | 0.2.1 e precedenti — tutte le versioni pubblicate |
| Corretta in | nessuna |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.4 Alto (trasporto stdio). AV:N → 9.8 Critico se il server è incapsulato in un trasporto di rete. |
| Segnalato da | s1ko (github.com/s1ko, [email protected]) |
| CVE assegnata | 2026-07-13, MITRE CNA-LR |
Gli argomenti degli strumenti MCP sono influenzati dall'attaccante. Sono prodotti da un LLM a partire
dal contenuto che l'agente elabora — documenti, pagine web, output di strumenti — quindi
l'iniezione indiretta di prompt mette un attaccante in controllo dei valori che un gestore di strumento
riceve. Un gestore che passa uno qualsiasi di questi valori a una shell trasforma
tale influenza in esecuzione di codice sull'host che esegue il server MCP. Questo è
lo stesso modello del caso precedente aws-mcp-server / CVE-2026-5058.
Un server di conversione multimediale è un bersaglio particolarmente naturale per questo: i file che gli vengono chiesti di elaborare sono esattamente il contenuto non attendibile che un agente raccoglie altrove.
src/utils/ffmpeg.ts — il comando viene assemblato come stringa e la shell è
abilitata esplicitamente:
function runProcess(command: string, args: string[], useShell = false) {
const child = spawn(command, args, { shell: useShell, windowsHide: true });
…
}
export async function runFFmpegCommand(command: string): Promise<string> {
const { stdout, stderr, code } = await runProcess(`ffmpeg ${command}`, [], true);
…
}
spawn("ffmpeg " + command, [], { shell: true }) esegue l'intera stringa tramite
/bin/sh -c. Tutto ciò che il chiamante ha contribuito a command è sintassi della shell.
src/tools/handlers.ts raggiunge quell'helper da tre strumenti, interpolando
parametri che non vengono mai validati nel contenuto:
| Strumento | Parametri iniettabili |
|---|---|
convert_video | options |
extract_audio | format |
create_video_from_images | codec, pixelFormat, extraOptions |
Solo inputPath e outputPath vengono controllati, e gli schemi Zod
validano il tipo (z.string()), mai il contenuto — quindi i metacaratteri passano direttamente.
Una chiamata a convert_video con options impostato a ; touch /tmp/marker ; produce:
/bin/sh -c "ffmpeg -i /tmp/in.mp4 ; touch /tmp/marker ; /tmp/out.mp4"
poc/driver.mjs comunica tramite MCP su stdio: inizializza il
server, invia una singola tools/call per convert_video con un valore options
iniettato e verifica la presenza di un file marcatore. Il payload è un touch benigno.
npm pack @sworddut/[email protected]
tar xf sworddut-mcp-ffmpeg-helper-0.2.1.tgz && cd package && npm install
node ../poc/driver.mjs
Atteso su una versione interessata:
==== POC RESULT (@sworddut/mcp-ffmpeg-helper) ====
marker /tmp/PWNED_ffmpeg created: true
verdict: CONFIRMED — command injection executed
ffmpeg non deve essere installato — il comando iniettato viene eseguito nella stessa stringa /bin/sh -c indipendentemente dal fatto che il binario iniziale venga risolto. Convalidato il 2026-06-01 in un container isolato, riconvalidato il 2026-06-13, e il sink riconfermato presente sul branch predefinito il 2026-08-22. Eseguilo solo contro infrastrutture che sei autorizzato a testare.
ffmpeg contenente ;, &&, ||, |, un backtick o $(. Le invocazioni legittime di ffmpeg da questo server non ne contengono.sh -c la cui riga di comando inizia con ffmpeg e contiene un secondo comando dopo un separatore — un segnale a livello di albero dei processi (auditd, eBPF, Falco, EDR) che non dipende dal logging dell'applicazione.ffmpeg e ffprobe sono attesi; una shell, un interprete o un client di rete non lo sono.Running FFmpeg command: ffmpeg <command>, che è il punto più economico per individuare un valore iniettato se i log vengono raccolti.options, format, codec, pixelFormat o extraOptions contengono metacaratteri della shell.MITRE ATT&CK T1059.004 Command and Scripting Interpreter: Unix Shell.
Non esiste una release corretta, quindi le opzioni sono il contenimento e la rimozione:
runFFmpegCommand.La correzione upstream consiste nel rimuovere shell: true e passare a ffmpeg un vettore di argomenti — spawn("ffmpeg", ["-i", inputPath, …]) — costruendo tale array da valori format, codec e pixelFormat in allowlist anziché da stringhe libere. La validazione del contenuto, non solo la validazione dei tipi Zod, è il requisito di fondo.
NIST SP 800-53r5 SI-10; OWASP ASVS v4 §5.3.8; mitigazioni CWE-78 M1 e M2.
| Data | Evento |
|---|---|
| 2026-05-29 | Vulnerabilità identificata tramite revisione del codice sorgente del tarball pubblicato |
| 2026-06-01 | Convalidata dinamicamente tramite MCP stdio in un container isolato |
| 2026-06-13 | Riconvalidata su un secondo host; il repository non ha il Private Vulnerability Reporting abilitato, e i campi repository/bugs/homepage di package.json sono lasciati al template github.com/yourusername, senza alcun contatto di sicurezza documentato |
| 2026-07-13 | MITRE CNA-LR assegna CVE-2026-52617, s1ko accreditato come scopritore |
| 2026-08-22 | Sink riconfermato sul branch predefinito; npm latest è ancora 0.2.1; pubblicato questo write-up |
aws-mcp-server)Avvisi complementari dalla stessa sessione di ricerca: CVE-2026-52616, CVE-2026-52618.
MIT — vedi LICENSE.