FlawOpen

flawopen.com/Teardowns/cve-2026-105697-langflow-mcp-stdio-command-injection

● CVE-2026-105697 · CVSS 9.9[1] · Критический
Исследования · FlawOpen

CVE-2026-105697: внедрение команд MCP в Langflow

До версии 1.10.3 Langflow передавал конфигурацию MCP stdio процессу, запускаемому через оболочку. На доступном извне экземпляре с LANGFLOW_AUTO_LOGIN=true атакующий мог получить токен без учётных данных; при отключённом автоматическом входе для выполнения команд на хосте всё ещё было достаточно аутентифицированного пользователя не администратора. Версия 1.10.3 проверяет все пути, включая момент перед запуском, и запускает программу без оболочки.[1], [2], [3]

Вектор CVSSCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H[1]
💡 Простыми словами (ELI5)

Представьте сотрудника, который получает фразу, где пунктуация может изменить задачу: один знак способен превратить указание о доставке во второй приказ. Langflow передавал настроенную команду оболочке, которая воспринимает такую синтаксическую запись как управляющую, вместо того чтобы передавать программу и аргументы как отдельные данные. Исправление проверяет разрешённую команду и запускает программу напрямую, без оболочки.[1], [2]

Ключевые понятия и термины

Транспорт MCP stdio
Запускает MCP-сервер как локальный дочерний процесс и обменивается сообщениями через стандартные потоки ввода и вывода.[1], [2]
Внедрение команд (CWE-78)
Внешне контролируемый текст изменяет команду ОС, передаваемую оболочке или средству запуска процесса.[1], [5]
Точка запуска
Последний участок кода, создающий процесс; проверка нужна здесь, даже если API уже выполнял проверки.[1], [2]
Встроенная конфигурация flow/tweak
Настройки MCP, включённые в flow или runtime-переопределение, а не созданные через API настроек.[1], [2]

Связи со стандартами

  • Ссылка CWE для слабого места, описанного в этом руководстве: CWE-78

Анализ первопричины

До версии 1.10.3 конфигурация MCP stdio объединяла команду и аргументы в строку, а затем запускала её через bash -c. В версии 1.9.0 API настроек получила список разрешённых команд и проверки аргументов и окружения, однако MCP Tools, встроенные в flow или переданные через tweak, могли обойти проверку модели: на точке запуска общей политики не было. В Langflow 1.10.3 проверка сосредоточена в lfx.base.mcp.security.validate_mcp_stdio_config, применяется к API, flow, tweak, устаревшему компоненту и непосредственно перед запуском; оболочка удалена. CVE-2026-105697 относится к CWE-78, CVSS 3.1 — 9.9. Если автоматический вход отключён, атакующему всё равно нужна учётная запись не администратора с возможностью настроить или выполнить соответствующий путь MCP; включённый по умолчанию автоматический вход может открыть доступ к опубликованным тестовым экземплярам без учётных данных.[1], [2], [4], [5]

Пошаговый сценарий атаки

Шаг 1

Пользователь достигает пути настройки MCP

В уведомлении описан доступ через настройки MCP-сервера или flow с компонентом MCP Tools. На доступном извне экземпляре с настройкой разработки LANGFLOW_AUTO_LOGIN=true атакующий мог получить токен без учётных данных. При отключённом автоматическом входе всё ещё могло быть достаточно аутентифицированного пользователя не администратора.[1]

Шаг 2

Конфигурация поступает в подготовку процесса

Команда и аргументы формируют command_str при подготовке подключения MCP stdio.[1]

Шаг 3

Оболочка интерпретирует строку

До 1.10.3 запуск использовал bash -c; выполнение начиналось при попытке подключения, ещё до успешного MCP handshake.[1]

Шаг 4

Проверки на входе неполны

Версия 1.9.0 проверяет настройки REST, но конфигурации flow и tweak могут обойти проверку модели.[1]

Шаг 5

Процесс хоста работает с правами Langflow

Команда запускается от имени пользователя службы Langflow. Интерфейс при этом может сообщить о неудачном запуске MCP-сервера.[1]

Шаг 6

Версия 1.10.3 закрывает точку выполнения

Общая политика проверяет каждую точку входа и состояние прямо перед запуском; программа запускается без оболочки.[1], [2]

Исходный код: Уязвимый vs Защищённый вариант

Уязвимый фрагмент показывает описанный в уведомлении запуск через оболочку; это не исполняемый эксплойт. Исправленный фрагмент отражает подход версии 1.10.3: общая политика проверяет конфигурацию на каждой точке входа и повторно непосредственно перед созданием процесса, а API получает исполняемый файл и аргументы отдельно. Прямой запуск исключает интерпретацию оболочкой, но сам по себе не делает безопасными все разрешённые программы и пакеты; операторам также нужны соответствующие меры контроля источников пакетов и изоляции.[1], [2]

Фрагмент исходного кода: lfx/base/mcp/util.py — целевые фрагменты исходного кода

УЯЗВИМАЯ РЕАЛИЗАЦИЯ
# Уязвимый способ запуска из уведомления (фрагмент):
server_params = StdioServerParameters(
    command="bash",
    args=["-c", f"exec {command_str}"],
    env=env_data,
)
БЕЗОПАСНЫЙ ИСПРАВЛЕННЫЙ ВАРИАНТ
# Сокращённый вариант по исходному коду 1.10.3: проверить политику и запустить процесс напрямую.
command_parts = shlex.split(command_str)
if not command_parts:
    raise ValueError("MCP stdio command is required")
command, args = command_parts[0], command_parts[1:]
validate_mcp_stdio_config(command, args, env_data)  # Repeat at the execution boundary.
server_params = StdioServerParameters(
    command=command,
    args=args,
    env=env_data,
)  # No shell wrapper. The shared validator rejects disallowed configurations.

Чек-лист по защите системы для инженеров

Источники