MaxKB, корпоративная платформа для создания ассистентов с открытым исходным кодом, опубликованная на GitHub в организации 1Panel-dev, создала своих чат-агентов на базе фреймворка, который автоматически и незаметно добавляет оболочечный инструмент (shell tool) при передаче бэкенда с поддержкой оболочки — причем MaxKB никогда не удаляла этот инструмент и не требовала ничьего подтверждения для его использования. Данная уязвимость получила идентификатор CVE-2026-77521 и была опубликована 2 сентября 2026 года в виде бюллетеня безопасности GitHub GHSA-f36j-f34j-h3rx. Ее оценка по шкале CVSS 3.1 составляет 10.0 из 10 для случаев публичного или встроенного ассистента. Компания Lasso Security, которая обнаружила и сообщила об уязвимости, продемонстрировала, что текстовое сообщение в чате — или даже текст, просто поглощенный ассистентом через извлечение данных (retrieval) либо загруженный документ — может заставить модель выполнять команды: при развертывании на «голом железе» непосредственно на хосте, а также в официальном контейнере через обертку (wrapper), которую, по словам исследователей, можно обойти с помощью точки с запятой. Ни один из цитируемых источников не фиксирует случаев эксплуатации уязвимости «в дикой природе». Собственная оценка степени серьезности, анализ достоверности и список источников этой уязвимости находятся в архиве инцидентов ИИ вместе с соседними записями о MaxKB и инструментах агентов из того же пакета раскрытия.
MaxKB — это продукт для самостоятельного развертывания, предназначенный для создания ассистентов на основе дополненной генерации (RAG): оператор создает ассистента, наделяет его возможностями (инструменты, серверы Model Context Protocol, навыки, суبприложения), подключает базу знаний, сформированную из загруженных документов или просканированных веб-сайтов, а затем делает ассистента доступным либо через аутентифицированную консоль, либо в виде публичного встраиваемого виджета чата. Эта универсальность и является источником уязвимости. Условие срабатывания, описанное в бюллетене, заключается не в какой-то необычной конфигурации, а в самой обычной: любой ассистент хотя бы с одной подключенной функцией маршрутизирует свой чат через уязвимый путь агента, в то время как чат без подключенных функций этого не делает. В материале Lasso проект описывается как один из наиболее широко используемых в своей категории, а также отмечается, что MaxKB обычно развертывается как мультитенантная служба. Это приводит к тому, что команды выполняются с правами пользователя приложения в рамках всей модели аренды, а не изолированно внутри сегмента отдельного тенанта.
Оболочечный инструмент появился вместе с фреймворком, а не с продуктом
MaxKB строит таких агентов с помощью библиотеки deepagents от LangChain, версия которой зафиксирована на отметке 0.6.11 в файле pyproject.toml проекта как для уязвимого тега, так и для текущего. В файле apps/application/flow/tools.py в строке 467 тега v2.10.3-lts проект вызывает create_deep_agent с параметром backend, установленным в SandboxShellBackend — подкласс MaxKB, который выполняет команды на хосте. Согласно бюллетеню, deepagents автоматически внедряет набор инструментов при передаче такого бэкенда оболочки: execute, ls, read_file, write_file, edit_file, glob и grep. Они не являются частью аргумента tools=list, который содержит только собственные инструменты оператора, инструменты MCP и инструменты навыков. Их нельзя удалить из интерфейса или через конфигурацию.
MaxKB также не передает excluded_tools — аргумент библиотеки, который позволил бы их исключить. В бюллетене подробно объясняется, почему это важно даже в качестве меры устранения: excluded_tools «удаляет инструмент из того, о чем сообщается модели, но не из исполнителя». Разница между инструментом, о существовании которого модель не подозревает, и инструментом, который невозможно запустить, — это и есть вся суть данной уязвимости в миниатюре.
Защитный барьер, в котором перечислены три инструмента, а четвертый пропущен
Элемент управления с участием человека (human-in-the-loop) в том же вызове состоит из одной строки и перечисляет три операции: interrupt_on={"write_file": False, "read_file": False, "edit_file": False}. Запись файла, чтение файла и редактирование файла явно указаны по именам. Выполнение команд вообще отсутствует в качестве ключа в этом словаре. Согласно трактовке в бюллетене, это означает, что для команды execute не запрашивается никакого подтверждения: три файловые операции перечислены явно с настройкой отсутствия прерывания, а оболочечный инструмент вовсе не упомянут.
В совокупности путь атаки выглядит следующим образом: ненадежный текст достигает модели, модель вызывает execute, и команда выполняется. В бюллетене названы два способа доставки ненадежного текста. Первый, прямой — это чат: публичный или встроенный виджет либо беседа другого тенанта. Второй, непрямой — это контент, который поглощает ассистент: документ RAG, загруженный файл или веб-страница, которую платформа сканирует в базу знаний. Публикация Lasso делает второй путь наглядным, отмечая, что «круг людей, которые могут подбросить текст модели, шире круга людей, которые могут общаться с ней в чате».
Все, что MaxKB предпринимает для изоляции, происходит в файле apps/application/flow/backend/sandbox_shell.py, и в версии v2.10.3-lts это начинается со значения по умолчанию. В строке 9 написано _enable_sandbox = bool(int(CONFIG.get("SANDBOX", 0))), при этом параметр SANDBOX отсутствует в Config.defaults в файле apps/maxkb/conf.py. При отсутствии явной настройки MAXKB_SANDBOX значение равно нулю, ветвление с оберткой в строке 65 пропускается, а execute передается напрямую в subprocess.run с параметром shell=True на хосте от имени пользователя, запустить службу — root, если формулировать в терминах бюллетеня, когда служба запущенна с правами root.
Именно эту конфигурацию исследователи использовали для проверки концепции (PoC) на хосте. Они запустили настоящий код MaxKB из исходников с ненастроенным параметром MAXKB_SANDBOX, создали ассистент с одним подключенным инструментом и попросили его в одном сообщении чата выполнить команды получения информации о системе. Инструмент execute сработал и записал файл, содержимое которого представляло собой вывод команд uname, id и sw_vers самого хоста — вывод, который, как отмечается в бюллетене, гарантированно отсутствовал внутри любого контейнера. В Lasso также зафиксировали предел того, что их остановило: модель отказалась выполнять откровенно названный проверочный файл, в то время как благожелательные формулировки рабочих операций не вызывали отказа. Выравнивание модели (alignment), по их словам, представляет собой «частичного «лежачего полицейского», а не средство контроля».
В официальном образе песочница работала, но все равно допускала утечки
Официальный контейнер устанавливает MAXKB_SANDBOX=1 в базовом образе в файле installer/Dockerfile-base на строке 48, поэтому там активна обертка — и сама обертка представляет собой вторую уязвимость. Она формировала единую строку: env -i LD_PRELOAD=/opt/maxkb-app/sandbox/lib/sandbox.so, за которой следовали gosu sandbox, а затем переданная моделью команда, переданная оболочке, запущенной от имени root. Поскольку команда интерполировалась как текст, под действие gosu попадал только ее первый токен. Любая точка с запятой, конвейер (pipe), перенаправление или подстановка команд в выводе модели обрабатывались внешней оболочкой root до того, как песочница успевала их увидеть.
В отчете Lasso приводится рабочая структура такого сценария: полезная нагрузка вида env -i LD_PRELOAD=... PATH="$PATH" gosu sandbox ls; whoami; id, в которой команда ls изолирована, whoami — нет, а все, что идет после нее, выполняется свободно. В ходе тестирования исследователи записали файл, принадлежащий root, с помощью перенаправления в то время, как изолированная внутренняя команда была заблокирована. В довершение всего, ни installer/Dockerfile, ни installer/Dockerfile-base не содержат директивы USER, поэтому образ приложения запускается с UID 0 — в бюллетене сообщается о подтверждении прав root во время выполнения. Таким образом, контейнер все равно выполнял команды, а песочница решала лишь то, какие из них будут формально приписаны пользователю с низкими привилегиями.
Полный сценарий атаки, описанный Lasso, вообще не требует доступа к цели. Злоумышленник размещает команды на веб-странице, дожидается, пока агент жертвы просканирует ее в базу знаний, после чего жертва задает обычный вопрос. Ответ возвращается корректным и легитимным; внедренная команда curl уже отправлена на сервер злоумышленника. В рекомендательном бюллетене отмечается, что исследователи тестировали только собственные развертывания, а не какие-либо сторонние или хостинговые экземпляры MaxKB.
Что устанавливают источники и что просто не замерялось
Механизм, два режима развертывания, кредит и фиксированный релиз согласуются в четырех документах: бюллетене GitHub, записи NVD, опубликованной 21 сентября 2026 года, собственной технической статье Lasso от 10 сентября 2026 года и отчете GBHackers от 22 сентября 2026 года, который является единственным независимым освещением этого CVE в СМИ. Ни один источник не оспаривает ни одну часть находки, а в архиве запись зарегистрирована как бесспорная с наивысшей степенью достоверности.
Чего источники не содержат, так это какой-либо оценки масштабов воздействия. Нет данных о количестве развертываний MaxKB, количестве доступных из интернета или встроенных ассистентов, результатов сканирования, телеметрии и имен жертв. Ничто в материалах не указывает на то, что уязвимость использовалась против кого-либо, и собственная оценка эксплуатации CISA с этим согласна: блок SSVC, прикрепленный к записи NVD 22 сентября 2026 года, оценивает эксплуатацию как «poc» (концепция атаки), возможность автоматизации как «yes» (да), а техническое воздействие как «total» (полное). Модель EPSS от FIRST оценивала вероятность эксплуатации в ближайшие 30 дней в 1,05 процента (64-й перцентиль) по состоянию на 27 октября 2026 года, а сам CVE отсутствует в каталоге известных эксплуатируемых уязвимостей CISA по состоянию на 27 октября 2026 года. Собственная оценка архива отражает те же свидетельства: высокая степень серьезности, реальный ущерб — ложь.
Для оценки 10.0 следует указать ее область применения, поскольку это число чаще всего цитируется вне контекста. Это балл для случая публичного или встроенного ассистента, где вектор CVSS имеет вид AV:N/AC:L/PR:N/UI:N/S:C — доступность по сети, низкая сложность атаки, отсутствие привилегий, отсутствие взаимодействия с пользователем, с изменением области воздействия (scope change), поскольку команда внутри ассистента выходит за его пределы в хостовую операционную систему. Балл принадлежит CNA, в данном случае — программе бюллетеней GitHub, на которую также указывает идентификатор источника в записи CVE. NVD содержит тот же вектор в качестве вторичной метрики и по состоянию на 28 октября 2026 года перечисляет запись в статусе «Deferred» (отложено), что означает публикацию анализа автора, а не собственного анализа NVD.
Патч вышел за месяц до публикации бюллетеня
Хронология идет в обратном порядке от публикации, и это наименее интуитивная часть материалов. Lasso сообщила об уязвимости конфиденциально через канал бюллетеней GitHub 8 июля 2026 года. MaxKB ответила на следующий день, ограничив область действия отчета официальным образом и запросив контейнерную концепцию атаки (PoC); исследователи предоставили ее и обход песочницы 10 июля. Коммит с исправлением 594f50f2 появился 9 июля — через день после отчета — и переписал файл sandbox_shell.py так, что строка команды модели синтаксически разбирается первой, а префикс gosu применяется к каждой простой команде, а не только к первой, причем каждый список аргументов переобозначается в кавычки, чтобы подстановка не выходила за рамки родительской оболочки. В статье Lasso описывается применение префикса gosu «к каждой простой команде, а не только к первой».
Релиз, в который вошло исправление, v2.10.5-lts, был опубликован 6 августа 2026 года. Бюллетень GitHub был выпущен 2 сентября, NVD опубликовала CVE 21 сентября, блок SSVC от CISA был добавлен, а GBHackers опубликовали отчет 22 сентября, в то время как собственная статья Lasso появилась 10 сентября — в середине этой цепочки, а не в начале. Оператор, отслеживающий теги релизов, а не ленты бюллетеней, получил патч примерно за четыре недели до предупреждения.
Границы версий заслуживают большего внимания, чем им уделяет бюллетень, поскольку два основных источника расходятся во мнениях, а репозиторий разрешает этот вопрос. Поле формы бюллетени фиксирует затронутые версии как «<= 2.10.3-lts» с примечанием, что это было проверено на 2.10.3-lts и что уязвимый путь «вероятно» затрагивает все версии, создающие агентов таким образом. Собственная статья Lasso определяет затронутый диапазон как «<= 2.10.4-lts». Теги подтверждают более широкий диапазон: v2.10.4-lts, выпущенная 16 июля 2026 года, содержит тот же 75-строчный файл sandbox_shell.py, что и v2.10.3-lts, а переписанный 311-строчный файл впервые появляется в версии v2.10.5-lts. Оператор на версии 2.10.4-lts, прочитавший только диапазон бюллетеня, мог бы решить, что он вне зоны риска. Это было не так.
Чего исправление не сделало
То, что исправляет v2.10.5-lts, — это обертка: она больше не строит одну строку оболочки под корневым пользователем (root). Что оно не делает, так это ничего в отношении самого инструмента. Прямое чтение репозитория в теге v2.10.8-lts, опубликованном 22 октября 2026 года, показывает, что агент по-прежнему создается с backend=SandboxShellBackend, а переменная interrupt_on по-прежнему содержит ровно три ключа — write_file, read_file и edit_file — без execute. Первые две рекомендации бюллетеня по устранению уязвимостей — по умолчанию использовать бэкенд без возможности выполнения и добавить «execute»: True в карту утверждений — в этом релизе отсутствуют.
Рекомендация о переходе в безопасное состояние при сбое (fail-closed) появилась позже, в версии v2.10.7-lts, и она важна для режима развертывания, который находился в худшем положении. Опубликованная 15 октября 2026 года, она меняет строку в sandbox_shell.py с CONFIG.get("SANDBOX", 0) на CONFIG.get("SANDBOX", 1). Инсталляция на исходном коде или «голом железе» (bare-metal), в которой никогда не задавалась эта переменная, теперь имеет включенную по умолчанию обертку, а не выключенную, что в узком смысле представляет собой рекомендацию «переходить в безопасное состояние при сбое на неконтейнерных развертываниях». Бюллетень требовал большего в рамках того же раздела — чтобы процесс с возможностью выполнения отказывался запускаться, когда среда выполнения песочницы недоступна, — и отдельно требовал, чтобы обертка никогда не формировала строку команды для корневой оболочки (root shell). Что касается контейнеров, то это факт, а не рекомендация: ни installer/Dockerfile, ни installer/Dockerfile-base не содержат директивы USER в теге v2.10.8-lts, поэтому образ приложения по-прежнему запускается от имени root.
В совокупности состояние материалов по состоянию на 28 октября 2026 года выглядит следующим образом. Вторая половина уязвимости — песочница, из которой можно было сбежать с помощью точки с запятой — закрыта, а небезопасное состояние по умолчанию (fail-open) при развертывании на хосте устранено. Первая половина — инструмент выполнения (execute), который поступает с объектом бэкенда и не является ключом в карте утверждений — остается тем способом, которым MaxKB строит ассистента с поддержкой инструментов. Собственные рекомендации исследователей по устранению уязвимостей были узкими: обновиться до версии 2.10.5-lts или выше и запустить версию Docker с включенной песочницей. Издание GBHackers передало те же инструкции плюс расширенный список для администраторов: отключить бэкенды агентов с поддержкой командной оболочки, если выполнение кода не требуется явно, требовать подтверждения человека перед любым действием выполнения, запускать контейнеры не от имени root и относиться к просканированным страницам, RAG-документам и загруженным файлам как к ненадежным входным данным.
Другая запись по MaxKB из той же сентябрьской партии
Вторая запись архива по MaxKB из этой партии описывает другую уязвимость с более плачевным исходом. CVE-2026-77516, также опубликованная в NVD 21 сентября 2026 года, представляет собой обход прав доступа, а не внедрение команд: в версиях с 2.0.0 по 2.9.2 участник рабочего пространства с минимальной ролью, которому явно запрещен доступ к инструменту через WorkspaceUserResourcePermission, все равно мог связать идентификатор этого инструмента через tool_ids, skill_tool_ids или mcp_tool_ids и выполнить его через путь отправки агента или рабочего процесса. Путь отправки не применяет повторно разрешение для конкретного инструмента, которое обеспечивают выделенные маршруты инструментов, а выполнение инструмента расшифровывает параметры init_params на стороне сервера, поэтому вызывающий объект получает учетные данные, переносимые инструментом, в доступе к которому ему было отказано. Ее оценка составляет 5.4, а описание в NVD завершается предложением, которого нет у CVE-2026-77521: «На момент данного обзора исправленная версия недоступна».
Контраст — это самое полезное для любого специалиста, проводящего триаж этой пары. Ошибка, получившая оценку 10.0, имела исправление, зафиксированное в течение дня и выпущенное за месяц до ее публикации. У ошибки с оценкой 5.4 на момент выпуска CVE не было опубликовано ни одной исправленной версии.
То, что остается действительно открытым, меньше, чем предполагает оценка, и больше, чем подразумевает примечание к патчу. Находка не вызывает сомнений, а механизм был проверен из конца в конец в обоих режимах развертывания командой, которая ее обнаружила. Масштаб воздействия совершенно не измерен — никто не опубликовал информацию о том, сколько ассистентов MaxKB содержат инструмент, сколько из них доступны ненадежной стороне или сколько работают на хосте без песочницы, поэтому реальные последствия этой уязвимости зависят от привычек развертывания, которые ни один из цитируемых источников не учитывает. А та часть архитектуры, которая подняла оценку до максимума, все еще присутствует в текущем релизе: возможность, которая выполняет команды, прикрепленная по умолчанию и отсутствующая на карте, запрашивающей подтверждение у человека в первую очередь.









