
Advisory e prova de conceito para injeção de comandos do sistema operacional em um auxiliar MCP ffmpeg, com análise de causa raiz, orientação para detecção e mitigações para um pacote npm não corrigido.
runFFmpegCommand passa uma string construída a partir dos parâmetros da ferramenta MCP para
spawn(…, { shell: true }), de modo que metacaracteres de shell em options, format,
codec, pixelFormat ou extraOptions são executados no host que executa o servidor.
⚠ Não existe versão corrigida
Em 2026-08-22, a versão mais recente no npm é a 0.2.1, que é a versão afetada, e o sink ainda está presente no branch padrão do repositório. Não há para onde atualizar. Consulte Mitigação para saber o que os usuários podem fazer enquanto isso.
| CVE | CVE-2026-52617 |
| CWE | CWE-78 (Neutralização Incorreta de Elementos Especiais usados em um Comando do SO) |
| Pacote | @sworddut/mcp-ffmpeg-helper (npm) |
| Afetado | 0.2.1 e anteriores — todas as versões publicadas |
| Corrigido em | nenhuma |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.4 Alto (transporte stdio). AV:N → 9.8 Crítico se o servidor for encapsulado em um transporte de rede. |
| Reportado por | s1ko (github.com/s1ko, [email protected]) |
| CVE atribuído | 2026-07-13, MITRE CNA-LR |
Os argumentos das ferramentas MCP são influenciados pelo atacante. Eles são produzidos por um LLM a partir
do conteúdo que o agente processa — documentos, páginas web, saída de ferramentas —, de modo que
a injeção indireta de prompt coloca um atacante no controle dos valores que um manipulador de ferramenta
recebe. Um manipulador que alimenta qualquer um desses valores em um shell transforma
essa influência em execução de código no host que executa o servidor MCP. Este é
o mesmo modelo do caso precedente aws-mcp-server / CVE-2026-5058.
Um servidor de conversão de mídia é um alvo particularmente natural para isso: os arquivos que lhe são solicitados a processar são exatamente o conteúdo não confiável que um agente capta de outros lugares.
src/utils/ffmpeg.ts — o comando é montado como uma string e o shell é
habilitado explicitamente:
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 }) executa a string inteira através de
/bin/sh -c. Tudo o que o chamador contribuiu para command é sintaxe de shell.
src/tools/handlers.ts alcança esse helper a partir de três ferramentas, interpolando
parâmetros que nunca são validados quanto ao conteúdo:
| Ferramenta | Parâmetros injetáveis |
|---|---|
convert_video | options |
extract_audio | format |
create_video_from_images | codec, pixelFormat, extraOptions |
Apenas inputPath e outputPath são verificados, e os schemas Zod
validam o tipo (z.string()), nunca o conteúdo — portanto metacaracteres passam
diretamente.
Uma chamada convert_video com options definido como ; touch /tmp/marker ; produz:
/bin/sh -c "ffmpeg -i /tmp/in.mp4 ; touch /tmp/marker ; /tmp/out.mp4"
poc/driver.mjs comunica-se via MCP sobre stdio: ele inicializa o
servidor, emite uma tools/call para convert_video com um valor options injetado, e verifica a existência de um arquivo marcador. O payload é um 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
Esperado em uma versão afetada:
==== POC RESULT (@sworddut/mcp-ffmpeg-helper) ====
marker /tmp/PWNED_ffmpeg created: true
verdict: CONFIRMED — command injection executed
ffmpeg não precisa estar instalado — o comando injetado é executado na mesma
string /bin/sh -c, independentemente de o binário inicial ser resolvido ou não.
Validado em 2026-06-01 num contentor isolado, revalidado em 2026-06-13, e o
sink reconfirmado como presente no branch predefinido em 2026-08-22. Execute-o apenas
contra infraestrutura que está autorizado a testar.
ffmpeg contendo ;, &&, ||, |, um backtick ou $(.
Invocações legítimas de ffmpeg a partir deste servidor não contêm.sh -c cuja linha de comando começa por ffmpeg e contém um
segundo comando após um separador — um sinal de árvore de processos (auditd, eBPF,
Falco, EDR) que não depende do registo da aplicação.ffmpeg e ffprobe são
esperados; uma shell, um interpretador ou um cliente de rede não são.Running FFmpeg command: ffmpeg <command>, que é o local mais barato para
detetar um valor injetado se os registos forem recolhidos.options, format, codec, pixelFormat ou
extraOptions contêm metacaracteres de shell.MITRE ATT&CK T1059.004 Command and Scripting Interpreter: Unix Shell.
Não existe uma versão corrigida, pelo que as opções são a contenção e a remoção:
runFFmpegCommand.A correção upstream é remover shell: true e passar ao ffmpeg um vetor de
argumentos — spawn("ffmpeg", ["-i", inputPath, …]) — construindo esse array a partir de
valores de format, codec e pixelFormat permitidos em vez de a partir de
strings de formato livre. A validação de conteúdo, e não apenas a validação de tipos Zod, é o
requisito subjacente.
NIST SP 800-53r5 SI-10; OWASP ASVS v4 §5.3.8; mitigações CWE-78 M1 e M2.
| Data | Evento |
|---|---|
| 2026-05-29 | Vulnerabilidade identificada por revisão do código-fonte do tarball publicado |
| 2026-06-01 | Validada dinamicamente via MCP stdio num contentor isolado |
| 2026-06-13 | Revalidada num segundo host; o repositório não tem Private Vulnerability Reporting ativado, e os campos repository/bugs/homepage do package.json permanecem no modelo github.com/yourusername, não deixando qualquer contacto de segurança documentado |
| 2026-07-13 | O MITRE CNA-LR atribui CVE-2026-52617, com s1ko creditado como descobridor |
| 2026-08-22 | Sink reconfirmado no branch predefinido; npm latest ainda 0.2.1; este write-up publicado |
aws-mcp-server)Avisos complementares da mesma passagem de investigação: CVE-2026-52616, CVE-2026-52618.
MIT — ver LICENSE.