Назад

2026/10/28

Node2Shell (CVE-2026-111497): какие системы под угрозой и что делать прямо сейчас

Какие системы реально затрагивает CVE-2026-111497 в Brotli, насколько срочен каждый случай и как сейчас обновить, пересобрать, перезапустить и защитить.

Обновлено 27 октября 2026 г.

CVE-2026-111497, получившая прозвища «Node2Shell» и «HTTP2Shell», — это ошибка повреждения памяти в декомпрессоре Brotli. Brotli — это метод сжатия br, повсеместно используемый в вебе. Ошибка присутствует в библиотеке Brotli от Google в версиях с 1.0.3 по 1.2.0 [1]. Node.js включает эту библиотеку в свой состав, и проект Node.js присвоил проблеме уровень High для веток 22.x, 24.x и 26.x [2]. Тот же декодер входит в пакеты Python, системные библиотеки Linux, настольные приложения и инструменты разработчиков, поэтому реальная поверхность атаки намного шире, чем «серверы на Node.js».

Эта статья предназначена для команд, которым нужно быстро понять, затронуты ли они и что делать в первую очередь.

Итог: если какая-либо из ваших систем распаковывает данные Brotli, поступающие от того, кого вы не контролируете (клиент в интернете, внешний сайт, отправитель webhook, загруженный файл), считайте это срочным. Установите исправления, пересоберите, перезапустите, а до тех пор блокируйте br.

Что делает уязвимость

Декодер неправильно обрабатывает некорректный «block switch» (переключение блока) в сжатом потоке. Он воспринимает ошибку как «мне нужно больше входных данных», а не как «эти данные недопустимы», и продолжает дописывать байты в небольшой внутренний буфер фиксированного размера, пока не выйдет за его границу [2]. Злоумышленник, сумевший заставить ваше приложение распаковать специально сформированный поток Brotli, может повредить память процесса. Это может привести к следующему:

  • Аварийное завершение (отказ в обслуживании). Это наиболее надёжно достижимый исход.
  • Утечка памяти процесса. В ответах или логах могут оказаться фрагменты секретов, токенов или данных других пользователей.
  • Возможное удалённое выполнение кода. Node.js указывает RCE в числе возможных последствий [2]. Первый публичный proof of concept добился выполнения кода только на намеренно ослабленной сборке, однако с тех пор исследователи сообщили о ненадёжном выполнении кода на официальной немодифицированной сборке Node.js 24.22.0 [3].

Аутентификация не требуется: злоумышленнику достаточно доставить байты, которые попадут в декодер. Именно поэтому оценка CVSS 4.0 составляет 9.2 (Critical) [1]. Таким образом, ключевой вопрос для каждой системы звучит не «используем ли мы Brotli?», а «может ли недоверенная сторона заставить нас распаковать Brotli?»

Типичные сценарии использования и их риски

Случай 1: доступные из интернета API, принимающие сжатые тела запросов (наивысший приоритет)

Некоторые API-серверы на Node.js, BFF, API-шлюзы и эндпоинты загрузки распаковывают тела запросов, отправленные с Content-Encoding: br. Другие делают то же самое через middleware. Риск: любой анонимный клиент в интернете может отправить специально сформированное тело запроса. Последствия варьируются от многократного падения сервиса, то есть дешёвой DoS-атаки, до утечки памяти процесса, хранящего данные сессий и API-ключи. Срочность: экстренная. Установите исправления сегодня, а до этого блокируйте тела запросов с br на периметре.

Случай 2: сервисы, получающие контент извне (высокий приоритет)

Обработчики webhook, краулеры и скрейперы, сервисы предпросмотра ссылок и RSS, интеграции с платёжными или SaaS-системами, а также ИИ-агенты, просматривающие веб, — все они выполняют исходящие HTTP-запросы. Многие HTTP-клиенты отправляют Accept-Encoding: br и автоматически распаковывают ответ. В Python urllib3 и requests делают это всякий раз, когда установлен пакет Brotli или brotlicffi, даже если ваш код никогда его не импортирует. aiohttp ведёт себя так же, а httpx — если установлен с дополнительной зависимостью brotli [4]. Риск: вредоносный, скомпрометированный или подменённый удалённый сервер может атаковать ваш бэкенд через свой ответ. Злоумышленнику вообще не нужно проникать в вашу сеть: вы сами к нему обращаетесь. Срочность: высокая. В первую очередь обновляйте там, где адресаты запросов не являются полностью доверенными.

Случай 3: настольные приложения, ИИ-агенты для программирования и CLI со встроенной средой выполнения

Приложения Electron, CLI на базе Bun или Node и ИИ-инструменты для разработчиков содержат собственную копию среды выполнения. Обновление системного пакета node их не исправляет. Обновление приложения на диске тоже не исправляет уже запущенные копии: долгоживущие процессы держат старую среду выполнения в памяти до перезапуска. Риск: такие инструменты часто хранят учётные данные и загружают внешний контент, что сочетает случай 2 с привилегированным процессом. Срочность: высокая для инструментов, получающих недоверенный контент. Обновите их, а затем действительно перезапустите. Ловушку «обновлено, но всё ещё работает старый код» мы подробно разобрали в статье HTTP2Shell: почему обновление бинарного файла не устраняет уязвимость в запущенных процессах.

Случай 4: образы контейнеров и артефакты CI/CD

Образы, собранные FROM node:22, node:24 или node:26 до выхода исправления, по-прежнему содержат уязвимую среду выполнения, даже если хост обновлён. То же относится к включённым в поставку Python wheels и vendored-зависимостям. Риск: уязвимый код возвращается при каждом развёртывании и каждом событии автомасштабирования, пока образ не будет пересобран. Срочность: высокая для образов, на которых работают системы из случаев 1 и 2. Пересобирайте, а не просто перезапускайте.

Случай 5: системные библиотеки Linux, шрифты и обработка изображений

Дистрибутивы поставляют декодер в виде разделяемой библиотеки, например libbrotli1 в Ubuntu/Debian. Её используют curl и libcurl при включённом сжатии, FreeType для веб-шрифтов WOFF2, а косвенно — инструменты обработки изображений и документов, такие как Pillow. Риск: системы, которые рендерят загруженные пользователями шрифты или документы либо получают внешний контент через curl --compressed, могут получить недоверенные данные Brotli. Сервер, который никогда не передаёт внешние данные в эти библиотеки, на практике подвержен риску слабо. Срочность: в большинстве случаев средняя, но высокая для сервисов рендеринга документов или обработки загрузок. Ubuntu выпустила исправленные пакеты brotli для 22.04, 24.04, 26.04 и 26.10 [1]. Для RHEL, Oracle Linux и других дистрибутивов проверьте бюллетень безопасности вашего поставщика по пакету brotli, а не делайте предположений о его статусе.

Случай 6: исключительно внутренние системы с доверенными входными данными (более низкий приоритет)

Некоторые сервисы распаковывают Brotli только из данных, которые вы создаёте сами, например из внутренних кешей или собственных артефактов сборки. Риск здесь ниже, но не нулевой: злоумышленник, уже закрепившийся в системе, может использовать ошибку для дальнейшего продвижения. Срочность: установите исправления в следующем плановом цикле.

Что делать: шаги реагирования

Шаг 1: найдите, где декодируется Brotli (сегодня)

  • Node.js: проверьте node -v на каждом хосте, а также в каждом образе контейнера и CI-раннере. Найдите в коде и конфигурациях brotliDecompress, createBrotliDecompress и middleware для разбора тела запроса, которое распаковывает br.
  • Встроенные среды выполнения: составьте список используемых приложений Electron, CLI на Bun/Node и ИИ-агентов и зафиксируйте версию среды выполнения, встроенной в каждый из них, а не только версию приложения.
  • Python: pip show Brotli brotlicffi в каждом окружении и образе. Ищите httpx[brotli] и транзитивные зависимости в lock-файлах и SBOM.
  • Пакеты ОС: dpkg -l | grep brotli или rpm -qa | grep brotli, затем выясните, какие процессы фактически загружают библиотеку.
  • Расставьте приоритеты по описанным выше случаям: всё, до чего могут дойти недоверенные входные данные (случаи 1, 2, 3, а также 5 при наличии загрузок), обрабатывается в первую очередь.

Шаг 2: установите исправления для затронутых компонентов

  • Node.js: обновитесь до 22.23.4, 24.22.1 или 26.12.1 или более поздней версии [2].
  • Python: Brotli>=1.2.1 или brotlicffi>=1.2.1.0. Пересоздайте lock-файлы [4].
  • Upstream Brotli / vendored-код на C: 1.0.10, 1.1.1 или 1.2.1 в зависимости от ветки [1].
  • Пакеты ОС: установите обновление безопасности вашего дистрибутива для brotli / libbrotli.
  • Настольные приложения и агенты: обновитесь до релизов поставщика, в которых явно указано, что они содержат исправленную среду выполнения. Если поставщик ничего не опубликовал, считайте приложение непроверенным, а не безопасным.

Шаг 3: пересоберите, разверните заново и перезапустите

  • Пересоберите образы контейнеров на основе исправленных базовых образов и разверните их заново. Перезапуск старого образа не поможет.
  • Перезапустите каждый долгоживущий процесс, в который была загружена уязвимая библиотека: сервисы Node, воркеры, сеансы агентов и всё, что слинковано с системной библиотекой. Для заданий с состоянием и ИИ-агентов сначала завершите или передайте текущую работу, чтобы не потерять события и подтверждения в очереди.

Шаг 4: снизьте риски на время установки исправлений

  • Входящий трафик: отклоняйте тела запросов, у которых Content-Encoding содержит br, на обратном прокси, балансировщике нагрузки или WAF, прежде чем их увидит какой-либо декодер.
  • Исходящий трафик: одного лишь удаления br из Accept-Encoding недостаточно, поскольку вредоносный сервер всё равно может отправить br. Также отклоняйте ответы, приходящие с Content-Encoding: br, или отказывайтесь их декодировать [4].
  • Запасной вариант для Python: там, где обновление приходится отложить, удалите Brotli и brotlicffi, чтобы клиенты перестали декодировать br. Сначала протестируйте, поскольку некоторые серверы всё равно будут отправлять br.

Шаг 5: проверьте результат и следите за признаками эксплуатации

  • Подтвердите версию среды выполнения изнутри работающего процесса или контейнера, а не только через пакетный менеджер.
  • Повторно просканируйте образы и SBOM, чтобы убедиться, что никакая старая копия по-прежнему не подтягивается транзитивно.
  • Проверьте недавние логи на предмет необъяснимых сбоев, ошибок сегментации или циклов перезапуска в сервисах, обрабатывающих br. Серию сбоев из одного источника стоит расследовать как возможную попытку атаки.
  • Если сильно подверженный атакам сервис неожиданно падал до установки исправления, рассмотрите ротацию секретов, которые хранил этот процесс, поскольку раскрытие содержимого памяти исключить нельзя.

Сводка

СитуацияРискДействие
Публичный API декодирует тела запросов brКритическийОбновить немедленно; блокировать br на периметре
Бэкенд получает данные с внешних URL, webhooks или веб-страницВысокийОбновить немедленно; отклонять ответы br
Приложения Electron, ИИ-агенты или CLI со встроенной средой выполненияВысокийОбновить и перезапустить каждый работающий экземпляр
Старые образы контейнеров и артефакты CIВысокийПересобрать на исправленных базовых образах и развернуть заново
Системная библиотека используется для загрузок, шрифтов или curl --compressedСредний–высокийУстановить обновление ОС; перезапустить сервисы, которые её загружают
Только внутренние доверенные данныеНизкий–среднийОбновить в следующем цикле

Обновление пакета — это лишь половина работы. Угроза устранена только тогда, когда ни один работающий процесс, образ или встроенная среда выполнения больше не может декодировать недоверенные данные Brotli старым кодом.

Источники