Сгенерированная абстрактная иллюстрация на глубоком тёмно-синем фоне. Широкая конструкция моста аспидно-серого цвета простирается через весь кадр, а один прямоугольный порт на её левой грани открыт и светится янтарным светом. Через это отверстие поток небольших одинаковых блоков устремляется наружу по едва заметной сетке чертежа, пересекая тонкую пунктирную голубую границу, нарисованную на переднем плане, и не останавливается. В правом нижнем углу блоки попадают в невысокую полупрозрачную решётку соединённых узлов, напоминающую хранилище памяти. На изображении отсутствуют текст, буквы, цифры, люди, товарные знаки или логотипы организаций. Логотип OrcaRouter наложен в правом нижнем углу белой полосы под иллюстрацией.
AI Safety Incidents

RufRoot: один неаутентифицированный запрос к MCP-мосту Ruflo выполнил команды, украл ключи и отравил память ИИ

Автор

Rowan Sterling

Дата публикации

Новые модели · 20Все модели →
Бенчмарки: Artificial Analysis · обновляется ежедневно
Назад ко всем статьям

В 30 июня 2026 года, Noma Labs передала мейнтейнеру Ruflo рабочий эксплойт против самого проекта. Исследовательское подразделение Noma Security выяснило, что Ruflo — платформа оркестрации агентов с открытым исходным кодом, ранее выпущенная под названием Claude Flow — поставлялась со стандартной конфигурацией развёртывания Docker Compose, в которой её Model Context Protocol мост был привязан к порту 3001 на всех сетевых интерфейсах и вообще не требовал аутентификации. Одного HTTP-запроса к эндпоинту /mcp было достаточно, чтобы выполнить shell-команды внутри контейнера от пользователя node, и из этой оболочки злоумышленник мог прочитать все API-ключи LLM-провайдеров в окружении, выгрузить все сохранённые диалоги, запустить рои агентов, оплачиваемые за счёт ключей жертвы, и записать инструкции в хранилище обучения AgentDB, которые продолжали бы направлять ответы ИИ для каждого пользователя этого экземпляра. Уязвимость — CVE-2026-59726, получившая название RufRoot, оценена в CVSS 10.0 и исправлена в 3.16.3 в течение 24 часов. Ни один из прочитанных нами источников не сообщает о её эксплуатации в реальных атаках. Собственная запись архива об этой уязвимости, со списком источников и оценкой достоверности, находится в архиве инцидентов ИИ, рядом с другими записями об MCP и инфраструктуре, размещёнными вокруг неё.

Дефолт, который открыл дверь

Ruflo — это то, что Noma Labs называет мета-каркасом для агентов: самостоятельно размещаемый слой для роёв до 100 агентов, созданный для Claude Code и OpenAI Codex, с долговременной памятью и встроенным MCP-сервером для вызова инструментов. Обычная установка — та, что описывает Noma: клонируйте репозиторий, добавьте ключи API LLM, выполните docker compose up -d. Файл compose по умолчанию в проекте привязывал мост к 0.0.0.0 на порту 3001 и привязывал сопутствующий экземпляр MongoDB ко всем интерфейсам на 27017, с отключённой аутентификацией Mongo. Насколько широко это распространяется, зависит от брандмауэра, группы безопасности и сетевой сегментации вокруг развёртывания; по формулировке самой Noma, любой экземпляр, доступный по сети, был полностью эксплуатируем без аутентификации.

MCP Bridge — это сервер Express.js, который преобразует JSON-RPC-запросы, поступающие по HTTP, в вызовы к внутренней библиотеке инструментов Ruflo. В уязвимой строке эта библиотека содержала 233 инструмента, которые охватывают доступ к оболочке, операции с базами данных, управление агентами и хранение в памяти. В материале Noma без обиняков сказано, что это означает: «MCP Bridge — не случайный вспомогательный отладочный интерфейс; скорее, это центральная нервная система Ruflo. Каждый вызов инструмента, каждое действие агента, каждая операция с памятью проходит через MCP Bridge».

Слой аутентификации отсутствовал, а не был просто слабым. POST /mcp и POST /mcp/:group реализуют протокол MCP JSON-RPC и передают входящие запросы tools/call напрямую во внутреннюю функцию executeTool(). В Ruflo действительно имелся блок-лист команд, AUTOPILOT_BLOCKED_PATTERNS, предназначенный для остановки опасных операций оболочки, но в GitHub advisory прямо указано, что он «применялся только в потоке autopilot. POST /mcp и POST /mcp/:group обходили его». Таким образом, один неаутентифицированный вызов с именем ruflo__terminal_execute выполнял произвольные команды от имени пользователя node контейнера, записанного в рекомендации GitHub как uid 1000, без необходимости токена, сеанса или предварительного взаимодействия. Для последующего не требовалось повышения привилегий: учётные данные, API агентов, хранилище памяти и база данных были доступны из этой оболочки.

Цепочка в восьми шагах

Noma Labs опубликовала proof of concept из восьми шагов и подтвердила каждый шаг в реальном времени на развертывании Ruflo по умолчанию в AWS EC2, используя внеполосные обратные вызовы к Burp Collaborator для проверки выполнения и эксфильтрации. Эти шаги — не умозрительные последствия, надстроенные над теоретической уязвимостью; это продемонстрированная последовательность, и раздел рекомендаций по устранению в бюллетене написан для операторов, которые, возможно, уже находятся внутри неё.

A hand-built HTML card headed 'The RufRoot chain, step by step', kicker 'RufRoot - CVE-2026-59726', subtitle 'Eight steps Noma Labs confirmed live against a default Ruflo deployment on AWS EC2'. Eight rows, each with a circled step number, the action, and what it yielded. 1, call tools/list: enumerate the 233 exposed tools. 2, call ruflo__terminal_execute over POST /mcp: shell inside the bridge container as node, uid 1000, verified by an out-of-band callback. 3, run printenv: every LLM provider API key in the container environment. 4, call ruflo__swarm_init and ruflo__agent_spawn: attacker-controlled agent swarms running on the victim's keys and compute. 5, call ruflo__agentdb_pattern-store: a fabricated SOC2 policy in the learning store, steering future output for all users. 6, query MongoDB on port 27017: every stored conversation, title and metadata. 7, write /app/beacon.js and inject it into index.js, then kill PID 1: a backdoor that survives the container restart policy. 8, clear shell history: no forensic trace. A footer cites Noma Labs and CVE-2026-59726, and marks step 5 as the step a patched redeploy does not undo.

Разведка идёт первой, потому что список инструментов доступен любому вызывающему: tools/list возвращает все 233 записи без учётных данных. Выполнение команд следует из той же конечной точки, и proof-of-concept от Noma подтвердил это с помощью внеполосного обратного вызова, а не на основании вывода из тела ответа. Шаг с окружением — это тот, который превращает компрометацию хоста в проблему выставления счетов и потери данных: файл compose передавал ключи провайдера в контейнер, а серверные процессы наследовали полное окружение через { ...process.env }, поэтому один printenv вывел их. Затем эти ключи позволили ruflo__swarm_init и ruflo__agent_spawn запустить контролируемые атакующим рои, которые израсходовали квоту и вычислительные ресурсы жертвы.

Пятый шаг — тот, что переживает вторжение. Используя ruflo__agentdb_pattern-store, Noma внедрила сфабрикованную политику соответствия SOC2, которая предписывала ИИ встраивать контролируемый злоумышленником URL в каждый скрипт развертывания, который он впоследствии создавал. Поскольку AgentDB существует именно для того, чтобы сохранять подобные паттерны и поведение агента улучшалось от сессии к сессии, внедренная запись вела себя так, как система и была задумана. «В будущих диалогах выходные данные будут формироваться под влиянием злоумышленника, и пользователь никак не сможет это распознать», — говорится в отчете Noma. Издание Dark Reading, сообщившее об уязвимости 29 июля, попросило внешнего эксперта пояснить это различие: Джон Галлахер, вице-президент Viakoo, назвал это проблемой иного класса: «Это не эксплуатация недостатков программного обеспечения, это отравление памяти».

Остальные шаги — это стандартная постэксплуатация, выполненная с необычным удобством. MongoDB во внутренней сети Docker не имела аутентификации, поэтому злоумышленники установили клиент в /tmp, выгрузили переписку и отправили её наружу. Для закрепления они записали /app/beacon.js, добавили строку require('./beacon.js') в index.js и убили PID 1, после чего политика перезапуска Docker вернула контейнер к жизни с активным маячком. Последним шагом было очищение истории командной оболочки. Всё это стало следствием одного неаутентифицированного запроса; ничто в конфигурации по умолчанию не остановило цепочку ни на одном этапе.

Исправление — и то, до чего не дотянется патч

Мейнтейнер выпустил Ruflo 3.16.3 в течение 24 часов после раскрытия информации 30 июня, а GitHub опубликовал рекомендацию GHSA-c4hm-4h84-2cf3 1 июля 2026 года. Исправление, отслеживаемое в репозитории как ADR-166 и объединённое в пул-реквесте 2521, меняет значения по умолчанию, а не просто добавляет проверку:

• MCP-мост по умолчанию привязывается к 127.0.0.1; публичная привязка требует MCP_AUTH_TOKEN, а при отсутствии токена процесс завершается при запуске с фатальным сообщением.

• Промежуточное ПО для Bearer-токена со сравнением за постоянное время находится перед мостом.

• terminal_execute ограничен на стороне сервера флагом MCP_ENABLE_TERMINAL=true, по умолчанию выключен, и это ограничение одинаково применяется к /mcp, /mcp/:group и потоку автопилота — недостающее звено, которое позволяло раскрытой цепочке достичь оболочки.

• Для MongoDB требуется аутентификация, а для запуска контейнера необходим root-пароль.

• Контейнер bridge работает с корневой файловой системой, доступной только для чтения, с tmpfs; список разрешённых источников CORS заменяет wildcard, а регрессионные «замки» CI охватывают как статическую конфигурацию, так и поведение в рантайме.

Ничто из этого не удаляет запись, уже внесённую в AgentDB. Рекомендация предписывает операторам любого открытого экземпляра немедленно закрыть порты 3001 и 27017 с помощью межсетевого экрана, сменить ключи провайдера, провести аудит хранилища паттернов на наличие внедрённых agentdb_pattern-store записей и удалить их, провести аудит MongoDB на предмет несанкционированного вмешательства и пересобрать контейнеры из чистых образов. Её предупреждение необычно прямое: «Повторное развёртывание с исправлением само по себе НЕ отменяет отравление». В отчёте Noma делается тот же вывод — аудит хранилища паттернов является частью устранения последствий, а исправление — нет.

Причина структурная, а не небрежность. Хранилище паттернов, которое формирует будущий вывод модели, не имеет способа отличить законную усвоенную инструкцию от внедрённой злоумышленником; и то и другое поступает в виде паттернов, а система построена так, чтобы доверять им. Это превращает сетевую уязвимость в проблему целостности данных с неизвестным накопленным объёмом, и это означает, что оператору важно выяснить не только, был ли порт доступен, но и что сейчас содержится в памяти.

A hand-built HTML timeline card headed 'From disclosure to coverage', kicker 'RufRoot - disclosure timeline', subtitle 'Five dates, from the private report to the day the record was filed'. Six dated rows. 30 June 2026: Noma Labs discloses the flaw to Ruflo's maintainer with a working proof of concept. 1 July 2026: Ruflo 3.16.3 ships and GHSA-c4hm-4h84-2cf3 is published with CVSS 10.0. 9 July 2026: the CVE record for CVE-2026-59726 is published in the National Vulnerability Database, later marked Deferred. 29 July 2026: The Hacker News and Dark Reading report the flaw; Noma Labs publishes its research. 30 July 2026: SecurityWeek reports it, and the record is dated to this day. A separate amber note reads: no source we read reports exploitation in the wild at any point on this timeline. A footer cites The Hacker News, the GitHub advisory API, the NVD record and SecurityWeek.

Что установлено, а что — нет

Техническая запись здесь является первичной и согласованной. В уведомлении указан затронутый пакет (npm ruflo ниже версии 3.16.3), исправленная версия, точные конечные точки, пользователь контейнера и два порта; примечания к выпуску сопровождающего описывают ту же цепочку; публикация Noma предоставляет подробности доказательства концепции; а независимые издания — The Hacker News и Dark Reading 29 июля 2026 года, SecurityWeek 30 июля — сообщают о том же механизме, не добавляя противоречивых подробностей. Исследовательская заметка Cloud Security Alliance от 5 августа 2026 года повторяет последовательность и помещает её рядом с более ранними уязвимостями неаутентифицированных MCP и оркестрации агентов, которые она отслеживала. Архив присваивает записи уровень уверенности A, бесспорный, и отмечает её как веху; его оценка серьёзности для записи — высокая, отличная от самой оценки CVSS.

Одну деталь оценки стоит изложить точно, поскольку два основных документа расходятся. GHSA-c4hm-4h84-2cf3 имеет оценку CVSS 10.0 по вектору AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — именно изменение области действия выводит её на максимум. Копия того же уведомления на странице релиза 3.16.3 описывает оценку как «критическую — CVSS 9.8». Запись в National Vulnerability Database, проверенная 30 октября 2026 года, опубликованная 9 июля 2026 года и помеченная как Отложено, содержит оценку GitHub 10.0 в качестве вторичной метрики и не имеет собственной оценки, подготовленной NVD. Мы не нашли объяснения для строки 9.8, и этот материал не разрешает этот вопрос.

Показатели внедрения скромнее. Noma Labs на тот момент описывала проект как имеющий более 67 000 звёзд на GitHub, около 10 млн скачиваний и примерно 1 млн активных пользователей; The Hacker News, как резюмировал Cloud Security Alliance, приводил более 66 500 звёзд. Счётчики скачиваний и пользователей принадлежат самой Noma и независимо не проверялись. Количество звёзд репозитория на 30 октября 2026 года составляло 80 198 — это показатель охвата проекта, а не мера экспонирования, и ни один источник не опубликовал, сколько развёртываний на самом деле было доступно из сети.

A hand-built HTML card headed 'Established, and not', kicker 'RufRoot - evidence', subtitle 'What the advisory, the release notes and the research support, against what nobody has shown'. Two columns. The left column, headed 'Established', lists: CVE-2026-59726 affects npm ruflo below 3.16.3 and is patched in 3.16.3; the default compose file bound the MCP bridge to 0.0.0.0 on port 3001 and MongoDB to 27017 without authentication; POST /mcp and POST /mcp/:group reached 233 tools and terminal_execute with no credential, running as node, uid 1000; Noma Labs confirmed an eight-step chain live on AWS EC2 with out-of-band callbacks, including an AgentDB pattern injection; the advisory was published 1 July 2026 with CVSS 10.0 and the fix shipped within 24 hours of the 30 June disclosure; the archive record is confidence A, undisputed, no real harm recorded, GLOBAL, MCP and INFRA. The right column, headed 'Not established', lists: that anyone exploited the flaw in the wild; how many Ruflo deployments were actually network-reachable; that any instance's AgentDB was poisoned, since no audit results are published; whether 9.8 in the release notes or 10.0 in the advisory is the intended score; Noma's counts of 10M downloads and 1M active users, which no independent source confirms; that any operator received notice beyond the public advisory. A footer cites GHSA-c4hm-4h84-2cf3, the Ruflo 3.16.3 release notes, Noma Labs and SecurityWeek.

То, что не установлено, — это как раз та часть, которую проще всего раздуть. Ни Noma, ни сопровождающий, ни любое издание, которое мы читали, не утверждают, что уязвимость эксплуатировалась в реальных атаках, и в архиве по этой записи не зафиксировано реального ущерба. Proof of concept от Noma запускался на развёртывании, которое исследователи контролировали на EC2; это показывает, что допускает установка по умолчанию, а не то, что пострадал какой-либо конкретный производственный экземпляр. Не опубликовано никаких данных о количестве развёртываний Ruflo, доступных из интернета, и ни один оператор не опубликовал результаты аудита AgentDB, поэтому и численность затронутой популяции, и объём существующей отравленной памяти неизвестны. Рекомендация Cloud Security Alliance считать открытые развёртывания полностью скомпрометированными — это позиция по рискам, оправданная эксплуатацией без взаимодействия; это не доказательство того, что компрометация произошла.

Почему архив отмечает это как веху

Знаковый флаг архива опирается на нечто более конкретное, чем максимальная оценка. Уязвимость удаленного выполнения кода с оценкой CVSS 10.0 в популярном сервисе для самостоятельного размещения — это привычная история, и исправление здесь появилось в течение 24 часов. RufRoot отличается тем, что эксплуатация завершалась в собственном обучающем конвейере ИИ, где обычные меры — обновить, развернуть заново, закрыть порт — оставляют внедренную инструкцию на месте, и она продолжает формировать ответы. В заметке Cloud Security Alliance это рассматривается как практический пример паттерна, который она уже документировала в инструментах для агентов, включая цепочку контрольных точек LangGraph и неаутентифицированную поверхность AutoGen Studio, и утверждается, что постоянную память, используемую для формирования поведения агента, следует рассматривать как хранилище конфиденциальных данных, подлежащее мониторингу целостности, а не как кэш.

Такая переформулировка — это практический вывод. Видимый артефакт этого инцидента — исправленная зависимость и опубликованное уведомление; невидимый — тот паттерн, который всё ещё может содержаться в AgentDB оператора, и не существует опубликованного инструмента или сигнатуры, позволяющих отличить законную изученную политику от внедрённой. Для организаций, запускавших стандартный compose-файл за доступной сетью, полезный ответ — тот, который дают и Noma, и уведомление: считайте, что ключи были прочитаны, смените их и проверьте память, прежде чем доверять ответам, которые она выдаёт.

© 2026 OrcaRouter

Провайдерам

Управляете инференс-платформой? Разместите свои модели на OrcaRouter.

providers@orcarouter.ai

Присоединяйтесь к сообществу

Discordsupport@orcarouter.aiXLinkedInGitHubYouTube