
Консультативное уведомление и proof-of-concept для внедрения команд ОС во вспомогательном модуле MCP для ffmpeg, включая анализ первопричины, рекомендации по детектированию и меры по смягчению для неисправленного npm-пакета.
runFFmpegCommand передаёт строку, собранную из параметров инструмента MCP, в
spawn(…, { shell: true }), поэтому метасимволы оболочки в options, format,
codec, pixelFormat или extraOptions выполняются на хосте, где запущен сервер.
⚠ Исправленной версии не существует
По состоянию на 2026-08-22 последний релиз в npm — 0.2.1, и это уязвимая версия, а уязвимое место по-прежнему присутствует в ветке по умолчанию репозитория. Обновляться некуда. См. Способы смягчения, чтобы узнать, что пользователи могут сделать тем временем.
| CVE | CVE-2026-52617 |
| CWE | CWE-78 (Ненадлежащая нейтрализация специальных элементов, используемых в команде ОС) |
| Пакет | @sworddut/mcp-ffmpeg-helper (npm) |
| Затронуты | 0.2.1 и более ранние — все опубликованные версии |
| Исправлено в | нет |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.4 High (транспорт stdio). AV:N → 9.8 Critical, если сервер обёрнут в сетевой транспорт. |
| Сообщил | s1ko (github.com/s1ko, [email protected]) |
| CVE присвоен | 2026-07-13, MITRE CNA-LR |
Аргументы инструментов MCP находятся под влиянием атакующего. Их формирует LLM
на основе контента, который обрабатывает агент, — документов, веб-страниц,
вывода инструментов, — поэтому косвенная инъекция промпта даёт атакующему
контроль над значениями, которые получает обработчик инструмента. Обработчик,
передающий любое из этих значений в оболочку, превращает такое влияние в
выполнение кода на хосте, где запущен сервер MCP. Это та же модель, что и в
прецедентном случае aws-mcp-server / CVE-2026-5058.
Сервер конвертации медиа — особенно естественная цель для этого: файлы, которые ему поручают обрабатывать, — это ровно тот недоверенный контент, который агент подхватывает извне.
src/utils/ffmpeg.ts — команда собирается как строка, и оболочка
включается явно:
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 }) пропускает всю строку через
/bin/sh -c. Всё, что вызывающая сторона добавила в command, является синтаксисом оболочки.
src/tools/handlers.ts обращается к этому помощнику из трёх инструментов, подставляя
параметры, которые никогда не проверяются на содержимое:
| Инструмент | Параметры с возможностью инъекции |
|---|---|
convert_video | options |
extract_audio | format |
create_video_from_images | codec, pixelFormat, extraOptions |
Проверяются вообще только inputPath и outputPath, а схемы Zod
проверяют тип (z.string()), но никогда — содержимое, поэтому метасимволы проходят
напрямую.
Вызов convert_video с options, установленным в ; touch /tmp/marker ;, даёт:
/bin/sh -c "ffmpeg -i /tmp/in.mp4 ; touch /tmp/marker ; /tmp/out.mp4"
poc/driver.mjs взаимодействует с MCP через stdio: он инициализирует
сервер, выполняет один вызов tools/call для convert_video с внедрённым значением options
и проверяет наличие файла-маркера. Полезная нагрузка — безобидный touch.
npm pack @sworddut/[email protected]
tar xf sworddut-mcp-ffmpeg-helper-0.2.1.tgz && cd package && npm install
node ../poc/driver.mjs
Ожидается на уязвимой версии:
==== POC RESULT (@sworddut/mcp-ffmpeg-helper) ====
marker /tmp/PWNED_ffmpeg created: true
verdict: CONFIRMED — command injection executed
ffmpeg устанавливать не требуется — внедрённая команда выполняется в той же
строке /bin/sh -c независимо от того, разрешается ли ведущий бинарный файл.
Подтверждено 2026-06-01 в изолированном контейнере, повторно подтверждено 2026-06-13, а
наличие sink повторно подтверждено в ветке по умолчанию 2026-08-22. Запускайте это только
против инфраструктуры, которую вы уполномочены тестировать.
ffmpeg, содержащая ;, &&, ||, |, обратную кавычку или $(.
Легитимные вызовы ffmpeg с этого сервера их не содержат.sh -c, командная строка которого начинается с ffmpeg и содержит
вторую команду после разделителя — сигнал на уровне дерева процессов (auditd, eBPF,
Falco, EDR), не зависящий от логирования приложения.ffmpeg и ffprobe —
ожидаемы; оболочка, интерпретатор или сетевой клиент — нет.Running FFmpeg command: ffmpeg <command>, что является самым дешёвым местом для
обнаружения внедрённого значения, если логи вообще собираются.options, format, codec, pixelFormat или
extraOptions содержат метасимволы оболочки.MITRE ATT&CK T1059.004 Command and Scripting Interpreter: Unix Shell.
Исправленного релиза не существует, поэтому варианты — локализация и удаление:
runFFmpegCommand.Исправление в upstream — отказаться от shell: true и передавать ffmpeg
вектор аргументов — spawn("ffmpeg", ["-i", inputPath, …]) — формируя этот массив из
значений format, codec и pixelFormat из белого списка, а не из
свободноформатных строк. Валидация содержимого, а не только проверка типов Zod, является
основным требованием.
NIST SP 800-53r5 SI-10; OWASP ASVS v4 §5.3.8; смягчения CWE-78 M1 и M2.
| Дата | Событие |
|---|---|
| 2026-05-29 | Уязвимость выявлена при анализе исходного кода опубликованного tarball |
| 2026-06-01 | Динамически подтверждена через MCP stdio в изолированном контейнере |
| 2026-06-13 | Повторно подтверждена на втором хосте; в репозитории не включён Private Vulnerability Reporting, а поля repository/bugs/homepage в package.json оставлены в шаблоне github.com/yourusername, поэтому документированный контакт по безопасности отсутствует |
| 2026-07-13 | MITRE CNA-LR присваивает CVE-2026-52617, s1ko указан как первооткрыватель |
| 2026-08-22 | Sink повторно подтверждён в ветке по умолчанию; npm latest по-прежнему 0.2.1; эта публикация опубликована |
aws-mcp-server)Сопутствующие рекомендации из того же исследовательского прохода: CVE-2026-52616, CVE-2026-52618.
MIT — см. LICENSE.