Один POST-запрос без пароля открывал злоумышленнику командную оболочку внутри платформы для управления ИИ-агентами. Полученный доступ позволял похитить ключи от сервисов OpenAI и Anthropic, прочитать переписку пользователей, запустить подконтрольных агентов и внедрить вредоносные инструкции в постоянную память системы.
Исследователи Noma Labs обнаружили критическую уязвимость RufRoot в открытой платформе Ruflo . Проблема получила идентификатор CVE-2026-59726 и максимальную оценку CVSS 10.0. Уязвимость затронула версии Ruflo ниже 3.16.3.
Ruflo помогает разработчикам создавать группы ИИ-агентов, координировать совместную работу, сохранять контекст между сеансами и подключать внешние инструменты через Model Context Protocol. На момент публикации исследования проект набрал более 67 000 звезд на GitHub.
Центральным компонентом платформы служит MCP Bridge, сервер на базе Express.js, через который проходят вызовы инструментов и другие действия агентов. Компонент предоставлял доступ к 233 функциям, включая управление агентами, работу с памятью, операции с базами данных и запуск команд внутри контейнера.
Стандартная конфигурация Docker Compose публиковала порт 3001 на всех сетевых интерфейсах. Доступ из интернета зависел от настроек межсетевого экрана, облачных групп безопасности и сегментации сети, однако любой пользователь с сетевым доступом к MCP Bridge мог отправлять команды без токена, API-ключа или другой проверки подлинности.
Конечная точка POST /mcp принимала запросы JSON-RPC и напрямую передавала вызовы функции executeTool(). В Ruflo действовал список шаблонов, запрещавший опасные команды, но ограничение распространялось только на режим autopilot. Прямые обращения к MCP Bridge обходили защиту.
Среди открытых инструментов находился ruflo__terminal_execute, запускавший произвольные команды внутри контейнера от имени пользователя node с идентификатором UID 1000. Для выполнения кода исследователям хватило одного HTTP-запроса. Дополнительное повышение привилегий не требовалось, поскольку процесс уже имел доступ к переменным окружения, интерфейсам агентов, постоянной памяти и базе данных.
Злоумышленник мог прочитать API-ключи подключенных сервисов, сохраненные в переменных окружения. В список потенциально доступных учетных данных входили ключи OpenAI, Anthropic, Google и OpenRouter. Украденные ключи позволяли использовать оплаченные жертвой модели и вычислительные ресурсы для запуска подконтрольных групп агентов.
Noma Labs подготовила автоматизированную цепочку атаки из восьми этапов и проверила сценарий на стандартной установке Ruflo в AWS EC2. Исследователи перечислили все доступные инструменты, выполнили команды, получили ключи провайдеров ИИ, создали собственных агентов и выгрузили переписку из MongoDB.
База MongoDB работала во внутренней сети Docker без обязательной аутентификации. После получения командной оболочки атакующий мог установить клиент базы данных во временный каталог, скопировать сообщения, названия диалогов и сопутствующие метаданные, а затем передать информацию на внешний сервер.
Отдельную угрозу создавало отравление постоянной памяти AgentDB. Злоумышленник мог сохранить вредоносное правило, например требование добавлять подконтрольный адрес во все создаваемые сценарии развертывания. Внедренная инструкция влияла на будущие ответы и сохранялась после установки обновления.
Специалисты Synack обратили внимание, что обычное исправление кода не восстанавливает доверие к скомпрометированной памяти. Вредоносная запись могла измениться при обработке, попасть в другие шаблоны или сохраниться в нескольких местах, поэтому администраторам требуется отдельная проверка AgentDB.
Исследователи также продемонстрировали установку постоянного бэкдора. Основной файл index.js был защищен от записи, но каталог /app разрешал создавать новые файлы. Атакующий мог сохранить вредоносный сценарий, подключить файл к процессу запуска и остановить основной процесс контейнера. Политика Docker restart: unless-stopped автоматически перезапускала Ruflo вместе с бэкдором.
Разработчики закрыли уязвимость в версии 3.16.3. Согласно официальному бюллетеню безопасности , MCP Bridge теперь по умолчанию принимает соединения только с локального компьютера. Публичный запуск требует токен MCP_AUTH_TOKEN, а выполнение команд через terminal_execute остается отключенным без явной настройки MCP_ENABLE_TERMINAL=true.
В рамках исправления ADR-166 разработчики также добавили обязательную аутентификацию MongoDB, перевели контейнер в режим только для чтения, подключили временную файловую систему tmpfs, ограничили разрешенные источники CORS и внедрили автоматические тесты небезопасных настроек.
Владельцам доступных по сети установок Ruflo рекомендовали немедленно закрыть порты 3001 и 27017, обновить платформу как минимум до версии 3.16.3 и заменить все API-ключи, которые находились в окружении контейнера. Администраторам также следует проверить MongoDB на вмешательство и удалить посторонние записи из AgentDB.
RufRoot не использовала взлом языковой модели, обход ограничений или внедрение инструкций через пользовательский запрос. Атака была направлена на инфраструктуру вокруг агентов: сетевой сервис, инструменты, контейнер, учетные данные, базу данных и постоянную память. Официальные рекомендации по защите MCP требуют аутентифицировать запросы, ограничивать права инструментов и не открывать чувствительные сервисы в сеть без необходимости.
Даже после обновления владельцы скомпрометированных установок не могут ограничиться повторным развертыванием контейнера. Исправленная версия закрывает уязвимый вход, но не удаляет ключи, переписку или вредоносные инструкции, которые злоумышленник успел скопировать или сохранить в памяти агентов.