Marimo RCE за 9 часов 41 минуту: атакующие собрали эксплойт прямо по advisory
Pre-auth RCE в Marimo эксплуатирован за 9 ч 41 мин после раскрытия — без публичного PoC, на эксфильтрацию ключей уходит меньше трёх минут. Обновитесь до 0.23.0.
Новости TprogerЕсли у вас в dev- или ML-стеке крутится Marimo — открытая альтернатива Jupyter с реактивными ячейками — откройте marimo --version прямо сейчас. Любая версия до 0.23.0 даёт любому, кто достучится до порта, полноценный root-shell без пароля за одно WebSocket-соединение.
CVE-2026-39987 (CVSS 9.3) — критическая pre-auth RCE (удалённое выполнение кода до авторизации) в популярном реактивном Python-ноутбуке. По данным Sysdig, первая эксплуатация в дикой природе зафиксирована через 9 часов 41 минуту после публикации advisory — без публичного PoC. Кража учётных данных из honeypot заняла меньше трёх минут.
Ключевые выводы
- Marimo до версии 0.20.4 включительно уязвим к CVE-2026-39987 — pre-auth RCE с CVSS 9.3. Патч: обновиться до 0.23.0.
- Корень проблемы — WebSocket-эндпоинт /terminal/ws пропускал вызов validate_auth(), который у соседнего /ws есть. Одного WebSocket-хендшейка достаточно для полного PTY-шелла.
- Attackers поймали тайминг: 9 ч 41 мин от раскрытия до реальной атаки, эксплойт собран по описанию advisory, без готового PoC.
- В Docker-сборках Marimo по умолчанию работает от root, а в .env лежат ключи OpenAI, Anthropic, Google Gemini, cloud-credentials — типичная цель атаки.
- Это третий RCE подряд в AI-тулчейне за несколько месяцев: Langflow CVE-2026-33017 (эксплойт через 20 ч), Flowise CVE-2025-59528. Паттерн устойчив.
В чём уязвимость
WebSocket — протокол постоянного двустороннего соединения между браузером и сервером; одно соединение висит долго и гоняет по нему сообщения. Сервер Marimo держит несколько таких эндпоинтов: /ws — для обмена состоянием ячеек и UI, /terminal/ws — для встроенного терминала внутри интерфейса ноутбука. Первый корректно вызывает validate_auth() (проверка сессионного токена пользователя) перед принятием соединения. Второй — нет.
Вместо аутентификации /terminal/ws проверял только две вещи: включён ли терминальный режим и поддерживает ли платформа PTY (псевдотерминал — эмуляция tty-интерфейса, через который обычно общаются командные оболочки). В сетевом деплое обе проверки почти всегда истинны. Итог — любой сетевой соседний или интернет-доступный атакующий открывает WebSocket, получает PTY-шелл с правами процесса Marimo. В дефолтном Docker-образе это root.
Endor Labs охарактеризовали баг как «root в один запрос»: один WebSocket-хендшейк — и атакующий внутри. Уязвимость зарегистрирована как GHSA-2679-6MX9-H9XC, CWE-306 (Missing Authentication for Critical Function). Исправлена в PR #9098.
Как выглядела эксплуатация
Advisory для CVE-2026-39987 опубликовали 8 апреля 2026 года. Sysdig разворачивает honeypot-инфраструктуру с уязвимыми Marimo-инстансами в нескольких облаках — первое срабатывание пришло через 9 часов 41 минуту, без публичного PoC. Описание advisory было достаточно точным, чтобы собрать рабочий эксплойт прямо по нему.
Дальше атакующий действовал методично. Подключился к /terminal/ws, прошёлся по файловой системе, прочитал .env, поискал SSH-ключи и конфиги. Полный цикл от коннекта до эксфильтрации учётных данных — меньше трёх минут. Через час атакующий вернулся проверить, не пришли ли другие.
Ни майнеров, ни бэкдоров не поставили. Sysdig интерпретирует это как работу живого оператора, который идёт по списку целей и возвращается за результатом, — а не как массовый автоматизированный скан.
Marimo не один: RCE в AI-тулчейне становится паттерном
Marimo используют инженерные команды Stanford, Mozilla AI, OpenAI и BlackRock. У проекта около 20 000 звёзд на GitHub, типичные деплои — Docker, Hugging Face Spaces, SkyPilot, CoreWeave. В этих окружениях под рукой обычно всё, что атакующий и ищет: ключи OpenAI, Anthropic и Google Gemini, cloud-credentials, SSH-ключи к training-серверам и бакетам с датасетами.
Компрометация Marimo-инстанса — это не просто shell на сервере. Это доступ к LLM-аккаунту с биллингом, к batch-инференсу на fine-tuned моделях, к облачному хранилищу с моделями и данными обучения. И это уже третий похожий инцидент за несколько месяцев: Langflow CVE-2026-33017 (эксплойт за 20 часов), Flowise CVE-2025-59528 (CVSS 10.0, активная эксплуатация спустя полгода после патча). Паттерн устойчивый: AI-тулчейн попадает в «серую зону» безопасности — воспринимается как dev-инструмент, а не production, и получает меньше мониторинга и сегментации сети.
Что делать прямо сейчас
- Обновите Marimo до 0.23.0 или выше. Проверка:
marimo --version. Для Docker — обновите базовый образ и pinned-зависимости. - Проверьте, был ли ваш инстанс доступен из сети после 8 апреля 2026 года. Если да — считайте учётные данные скомпрометированными и ротируйте их: ключи LLM-провайдеров (OpenAI, Anthropic, Google), cloud-credentials, SSH-ключи, токены пакетных менеджеров.
- Проверьте биллинг и активность в админках LLM-провайдеров и облаков — есть ли запросы или инстансы, которых вы не запускали.
- Не выставляйте Marimo в интернет напрямую. Минимум — запуск на loopback:
marimo edit --host 127.0.0.1. Публичный деплой — только за реверс-прокси с авторизацией (nginx basic-auth / auth_request, Caddy + OAuth2-Proxy), в VPN или в private subnet. - Разверните Marimo от непривилегированного пользователя, не от root. Стандартный Docker-образ работает как root — поправьте в своей сборке через USER в Dockerfile.
- Подпишитесь на GitHub Security Advisories для репозиториев AI-тулчейна: на странице репо в GitHub — Watch → Custom → Security alerts. Или добавьте в rss-агрегатор фид
github.com/owner/repo/security/advisories.atom. Для кросс-платформенного мониторинга — osv.dev и CISA KEV.
Индикаторы компрометации
Искать в логах веб-сервера или прокси перед Marimo:
Marimo сам логи WebSocket-соединений не пишет. Если Marimo стоит за reverse-proxy — смотрите access-логи прокси: nginx в /var/log/nginx/access.log, Caddy и Traefik — в stdout контейнера. Без прокси проверить ретроспективно по логам не выйдет — остаётся только ротация секретов по принципу «предположи компрометацию».
Проверить файлы, к которым типично обращается атакующий после получения шелла:
Часто задаваемые вопросы
Что такое Marimo?
Open source реактивный Python-ноутбук, альтернатива Jupyter. Хранит ноутбуки как чистые .py-файлы, автоматически пересчитывает зависимые ячейки при изменении данных, поддерживает SQL и интерактивные UI-виджеты. Используется для дата-сайенса, ML и AI-разработки.
Я запускаю Marimo только на localhost — я в безопасности?
Если Marimo слушает только 127.0.0.1 и вы единственный пользователь машины — риск минимален. Но при запуске на shared-сервере или рабочей станции с другими учётными записями угроза сохраняется: любая соседняя программа сможет открыть WebSocket к localhost. И всё равно обновитесь.
Почему PoC не понадобился?
Advisory описал точное место (/terminal/ws) и характер бага (отсутствие validate_auth). Собрать WebSocket-клиент, подключиться к эндпоинту и получить PTY — 15 строк Python. Для атакующего с базовыми навыками это быстрее, чем ждать чужой эксплойт.
Что с биллингом LLM-провайдеров, если утекли ключи?
OpenAI, Anthropic и Google биллят запросы в рамках ваших лимитов. Атакующий либо прогонит свой трафик до исчерпания квоты, либо использует ключи для скрытого использования fine-tuned моделей. Проверьте usage-дашборды ретроспективно и отзовите/ротируйте ключи.
Насколько это массовая проблема?
Marimo — не Jupyter по распространённости, но активно используется в AI/ML-командах крупных организаций. Docker-деплои часто выставляют порт наружу. По данным Sysdig honeypot ловит реальные атаки — значит, кто-то уже сканирует публичные инстансы.
Выводы
CVE-2026-39987 — ещё один пример того, как удобная «фича для разработчика» превращается в точку входа для атакующего, если её не прогнали через ту же модель угроз, что и основной API. Встроенный терминал выглядел как локальный инструмент — на деле обслуживал тот же сетевой стек, что и весь остальной интерфейс.
Предположение, что атакующие охотятся только за массово развёрнутыми платформами, — неверно. Любое интернет-доступное приложение с критическим advisory — цель, независимо от популярности.
Практический вывод для команд, использующих AI-тулчейн: отнеситесь к Marimo, Langflow, Flowise и прочим notebook-платформам как к production-сервисам, а не как к dev-утилитам. Это значит patch management, сегментация сети, least privilege в контейнерах и мониторинг исходящего трафика. Десять часов от advisory до эксплойта — время реакции, на которое стоит рассчитывать.
Минимальная проверка за 30 секунд для любого notebook- или AI-сервиса в вашей инфраструктуре: запустите ss -tlnp | grep LISTEN на хосте и найдите порты, на которых сидит Jupyter, Marimo, Flowise, Langflow, Streamlit, Gradio. Если порт слушает на 0.0.0.0, а не на 127.0.0.1 — разберитесь, зачем и как он защищён. Если не знаете зачем — переведите на loopback или за прокси с авторизацией.
Источники: The Hacker News, Cloud Security Alliance, SecurityWeek.