
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 la sink è ancora presente nel ramo predefinito del repository. Non c'è nulla a cui aggiornare. Vedi Mitigazione per cosa possono fare gli utenti nel frattempo.
| CVE | CVE-2026-52617 |
| CWE | CWE-78 (Neutralizzazione impropria di elementi speciali usati in un comando del sistema operativo) |
| Package | @sworddut/mcp-ffmpeg-helper (npm) |
| Affected | 0.2.1 e precedenti — tutte le versioni pubblicate |
| Fixed in | nessuna |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 7.8 Alto (trasporto stdio). AV:N → 9.8 Critico se il server è avvolto in un trasporto di rete. |
| Reported by | s1ko (github.com/s1ko, [email protected]) |
| CVE assigned | 2026-07-13, MITRE CNA-LR |
Gli argomenti degli strumenti MCP sono influenzabili dall'attaccante. Sono prodotti da un LLM a partire dal
contenuto che l'agente elabora — documenti, pagine web, output degli strumenti — quindi
l'iniezione indiretta di prompt mette l'attaccante in controllo dei valori che un handler
di strumenti riceve. Un handler che inserisce uno di questi valori in una shell trasforma
quell'influenza in esecuzione di codice sull'host che esegue il server MCP. Questo è
lo stesso modello del precedente caso aws-mcp-server / CVE-2026-5058.
Un server di conversione multimediale è un obiettivo particolarmente naturale per questo: i file che gli viene chiesto di elaborare sono esattamente il contenuto non attendibile che un agente recupera da altrove.
src/utils/ffmpeg.ts — il comando viene assemblato come stringa e la shell viene
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 inserito in command è sintassi di shell.
src/tools/handlers.ts raggiunge quell'helper da tre strumenti, interpolando
parametri che non vengono mai validati per il 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 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 parla MCP su stdio: inizializza il
server, emette una tools/call per convert_video con un valore options
iniettato e verifica la presenza di un file marker. Il payload è un innocuo touch.
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.
Validato il 2026-06-01 in un container isolato, ri-validato il 2026-06-13 e la
sink riconfermata presente sul ramo predefinito il 2026-08-22. Eseguilo solo
contro infrastrutture che sei autorizzato a testare.
ffmpeg contenente ;, &&, ||, |, un backtick o $(.
Le invocazioni legittime di ffmpeg di questo server non le 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 di shell.MITRE ATT&CK T1059.004 Interprete di comandi e scripting: shell Unix.
Non esiste una release corretta, quindi le opzioni sono contenimento e rimozione:
runFFmpegCommand.La correzione a monte è rimuovere shell: true e passare a ffmpeg un vettore
di argomenti — spawn("ffmpeg", ["-i", inputPath, …]) — costruendo quell'array da
valori format, codec e pixelFormat consentiti piuttosto che da
stringhe libere. La validazione del contenuto, non solo la validazione del tipo Zod, è il
requisito sottostante.
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 | Validata dinamicamente su MCP stdio in un container isolato |
| 2026-06-13 | Ri-validata su un secondo host; il repository non ha la segnalazione privata di vulnerabilità abilitata, e i campi repository/bugs/homepage di package.json sono lasciati al template github.com/yourusername, senza lasciare un contatto di sicurezza documentato |
| 2026-07-13 | MITRE CNA-LR assegna CVE-2026-52617, s1ko accreditato come scopritore |
| 2026-08-22 | Sink riconfermata sul ramo predefinito; npm latest è ancora 0.2.1; questo report è stato pubblicato |
aws-mcp-server)Avvisi complementari della stessa ricerca: CVE-2026-52616, CVE-2026-52618.
MIT — vedi LICENSE.