Искаженный сжатый поток, проигнорированная ошибка и запись за пределами буфера. 21 октября 2026 года Node.js выпустила исправления для уязвимости записи за пределами буфера в поставляемом в комплекте декодере Brotli для версий 22.23.4, 24.22.1 и 26.12.1. Днем позже, 22 октября, Imperva сообщила о выполнении кода на официальном Docker-образе Node.js 24.22.0 для Linux arm64. Уязвимость, получившая идентификатор CVE-2026-111497, имеет базовую оценку 9.2 (критическая) по шкале CVSS v4.0 и широко известна как Node2Shell.
По состоянию на 23 октября подтвержденных случаев эксплуатации «в дикой природе» не зафиксировано, а Node2Shell не была добавлена в каталог известных эксплуатируемых уязвимостей (KEV) CISA. Тем не менее, публичный код подтверждения концепции (PoC) был протестирован, а разрыв между выходом патча и появлением PoC составил около суток. Специалистам по безопасности следует выявить все случаи, когда их сервисы Node.js декодируют данные Brotli из ненадежных источников, и в первую очередь пропатчить именно их.
Команда исследователей угроз Sysdig (TRT) проанализировала публичные материалы по Node2Shell, чтобы помочь защитникам понять, какие системы доступны для атак, что из заявленного было продемонстрировано на практике, какими средствами видимости во время выполнения можно обнаружить уязвимость и что можно предпринять до начала развертывания патчей в организации.
Хронология
Дата
Событие
14 октября 2026 г.
Node.js делает предварительный анонс релиза, указывая затронутые линейки и высокий уровень максимальной критичности
21 октября 2026 г., 10:38 UTC
Node.js выпускает версии v22.23.4, v24.22.1 и v26.12.1
21 октября 2026 г., 15:47 UTC
Появляется первый публичный репозиторий GitHub для данного CVE, примерно через пять часов после выхода исправления
21 октября 2026 г., ~19:27 UTC
Проект Brotli выпускает версии 1.0.10, 1.1.1 и 1.2.1, в каждой из которых упоминается CVE-2026-111497
22 октября 2026 г.
Публикуется запись Google о CVE с оценкой 9.2 по шкале CVSS v4.0
22 октября 2026 г.
Imperva публикует исследование, демонстрирующее выполнение кода в Node.js 24.22.0
Затронутые версии Node.js
Сама ошибка содержится в Brotli, а не в коде Node.js. Node.js поставляет собственную встроенную копию, поэтому исправление требует обновления самой среды выполнения.
В рекомендациях Node.js уязвимость оценивается как имеющая высокую степень критичности. Google оценивает ее как критическую уязвимость с балом 9.2 по CVSS v4.0. Тем не менее, степень серьезности может зависеть от особенностей окружения и того, имеет ли ваш код доступ к декодеру.
Версия Node.js
Окончание поддержки
Исправленная версия
26.x
30 апреля 2029 г.
26.12.1
24.x
30 апреля 2028 г.
24.22.1
22.x
30 апреля 2027 г.
22.23.4
25.x
1 июня 2026 г. (завершена)
Нет исправления
20.x
30 апреля 2026 г. (завершена)
Нет исправления
Node.js заявляет, что версии с завершенным сроком поддержки (EOL) всегда затрагиваются патчами безопасности. Организации, использующие Node.js 25, 20 или более старые версии, должны считать эти хосты уязвимыми, так как никаких дополнительных исправлений для них не будет.
Пакеты дистрибутивов требуют отдельной проверки. Трекер Debian, проверенный 23 октября, указывает nodejs 18.20.4 в bookworm, 20.19.2 в trixie, 24.21.0 в forky и 24.22.0 в sid как уязвимые, а также отмечает, что nodejs в Debian использует системную библиотеку Brotli. В этом случае исправление применяется к библиотеке, а не только к среде выполнения.
Пакет Brotli в Debian также уязвим во всех версиях, перечисленных в трекере, причем для них не указано ни одной исправленной версии. Трекер также показывает, что и brotli, и nodejs не исправлены в ветке разработки Debian unstable. По состоянию на 23 октября для обоих компонентов нет исправленных пакетов Debian. Debian оценивает запись nodejs как имеющую маловажную срочность (unimportant), что отличается от высокого рейтинга, присвоенного Node.js, хотя трекер не объясняет причину.
В записи CVE корневая ошибка локализована в библиотеке Brotli от Google версий с 1.0.3 по 1.2.0, а исправлена в 1.0.10, 1.1.1 и 1.2.1. Любое другое программное обеспечение, включающее сборку Brotli из этого диапазона, заслуживает дополнительного анализа или запроса к поставщику.
Однако влияние не ограничивается Debian. Пакеты для Ubuntu, Fedora, RHEL и Alpine также могут использовать системную библиотеку Brotli вместо встроенной копии. Следовательно, исправление поступает через пакет Brotli конкретного дистрибутива, и номер версии Node.js не гарантирует наличие патча в системе.
Согласно данным Aikido, Bun также подвержен уязвимости. Уязвимы все версии 1.4.3 и более ранние, а выпуск Bun 1.4.4 уже содержит исправление.
Как работает уязвимость Node2Shell (CVE-2026-111497)
Brotli — это формат сжатия. Node.js поддерживает его с помощью встроенного декодера в своем модуле zlib. В записи CVE описывается переполнение буфера в файле c/dec/decode.c и перечисляются два типа уязвимостей: запись за пределами буфера (CWE-787) и непроверенное возвращаемое значение (CWE-252).
Второй тип уязвимости объясняет механизм атаки. Специально сформированный поток объявляет один тип блока данных, а затем заставляет декодер переключить тип блоков. Корректный декодер должен остановиться с ошибкой. Неисправленный декодер игнорирует ошибку и продолжает работу, осуществляя запись за пределы своего буфера. Semgrep описывает лежащий в основе дефект следующим образом: декодер путает неполные входные данные с недопустимыми и продолжает обрабатывать поврежденный поток.
Исправление невелико. Node.js перенес (cherry-picked) коммит из основного репозитория Brotli (0ed4268a), который заставляет декодер немедленно завершаться с ошибкой при переключении блока, если в потоке заявлен только один тип блока. Node.js также добавил новую константу ошибки BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH.
Какие компоненты уязвимы (доступны для атаки)
Node.js не декодирует Brotli самостоятельно. Приложение подвергается опасности, когда его код или используемая им библиотека распаковывают данные Brotli, контролируемые злоумышленником. Semgrep подтвердил несколько точек входа:
Путь
Есть доступ к декодеру?
Подробности
Express 5 с express.json()
Да, по умолчанию
Express 5.3.0 зависит от body-parser ^2.3.0. Библиотека body-parser версии 2.x декодирует тела запросов br, а параметр inflate по умолчанию имеет значение true. Простой HTTP-сервер Node.js не декодирует входящие тела Brotli самостоятельно.
Express 4 с express.json()
Нет, не через body-parser
body-parser версии 1.20.x обрабатывает только deflate и gzip и возвращает 415 для других кодировок.
Server-side fetch()
Да, для ответов, контролируемых злоумышленником
Функция fetch в Node.js распаковывает ответ с помощью декодера Brotli всякий раз, когда заголовок Content-Encoding содержит br. Отправка Accept-Encoding: identity не предотвращает это. Функции, обращающиеся по URL-адресам, предоставленным пользователем, обычно являются потенциальными целями (например, вебхуки).
Прямое использование node:zlib
Да
Функция createBrotliDecompress() уязвима, если она принимает данные, контролируемые злоумышленником.
Koa (через co-body)
Да
Тела запросов Brotli передаются через co-body на этап распаковки. Semgrep также упоминает @koa/bodyparser, koa-body, Egg и Strapi.
Fastify с @fastify/compress
Да
Регистрация этого плагина добавляет распаковку запросов до того, как сработают парсеры типа контента (content-type) в Fastify.
Входящий путь должен быть приоритетным для защиты. При глобальном подключении body-parser может обрабатывать множество публичных маршрутов, принимающих тела запросов, в зависимости от условий Content-Encoding и настроек парсера. Тем не менее, исходящий путь также имеет значение. Если сервис организации запрашивает данные с сервера, контролируемого злоумышленником, полученный ответ может скомпрометировать сам сервис.
Это не значит, что Express 4 полностью безопасен. Данный анализ касается только body-parser. Другие промежуточные обработчики (middleware), фреймворки, обратные прокси-серверы и собственный код организации все еще могут выполнять декодирование Brotli.
Эксплуатация уязвимости Node2Shell: что было продемонстрировано, а что лишь заявлено
Компания Imperva продемонстрировала выполнение кода на официальном образе Node.js 24.22.0 для Linux arm64 и отметила, что для успешного выполнения потребовалось несколько попыток. На только что запущенных контейнерах без отладчика или измененных бинарных файлов тест завершился созданием маркерного файла, в то время как пропатченная версия 24.22.1 отклонила те же входные данные с ошибкой формата. Компания Imperva не стала публиковать свой эксплойт.
Что касается публичных PoC (доказательств концепции), то 22 октября в 20:28 по всемирному координированному времени (UTC) поиск по GitHub выдал 11 репозиториев. Одна из лабораторий сообщила о сбоях в Node.js 20.19.5, 22.23.3, 24.22.0 и 26.12.0 и отметила, что исправленные версии 22.23.4, 24.22.1 и 26.12.1 отклоняют те же входные данные. Другая команда сообщила об успешном локальном выполнении команд в трех случаях из трех, однако для этого потребовалась сборка, использующая неисправленную системную библиотеку Brotli, а также предсказуемая структура памяти. Эта команда заявила, что слепое удаленное выполнение с включенной рандомизацией адресов не сработало.
Тем не менее, часть доказательств выглядит неубедительно. Исследователи утверждают, что ни один поток Brotli не может привести к ошибочной записи в память, а реальным последствием является отказ в обслуживании (DoS). Независимый тест входных данных для фиксирующего коммита на Node.js 24.22.0 привел к ошибке как на неисправленной, так и на пропатченной сборке, поэтому один лишь этот тест не доказывает факт возникновения записи. В компании Konfirmity отмечают, что сам фиксирующий коммит описывает уязвимость как уязвимость низкой степени тяжести, которую непросто проэксплуатировать.
Надежное удаленное выполнение кода (RCE) на сегодняшний день было воспроизведено только в одной конфигурации. В то же время сбои исследователям воспроизвести было легко. Организациям следует рассматривать сбой как наиболее вероятный исход в любых условиях, а появление командной оболочки (shell) — как вполне реальный риск везде, где их сервис декодирует экземпляры данных Brotli, которые могут контролироваться злоумышленником.
Последствия уязвимости Node2Shell
На момент публикации в открытом доступе не было информации о сетевых червях, кампаниях по массовой эксплуатации уязвимостей или надежных кроссплатформенных эксплойтах. Однако исследователям удалось доказать следующее:
- Отказ в обслуживании: авторы публичных PoC сообщают, что на неисправленных версиях Node.js процесс завершается аварийно, согласно данным из описанных выше репозиториев. Злоумышленник может вывести из строя любой сервис, который декодирует данные Brotli, поступающие от пользователей.
- Выполнение кода в рамках процесса Node.js: компания Imperva продемонстрировала это на одном образе и архитектуре после многократных попыток. Код злоумышленника будет выполняться с правами процесса Node.js и сможет похитить данные.
- Утечка данных из памяти: по заявлению Vercel, исследователи продемонстрировали утечку данных из памяти и выполнение команд в процессе Node.js на неисправленных версиях 22.x, 24.x и 26.x. Даже если выполнение кода завершается неудачно, утечка памяти может раскрыть такие данные, как учетные данные.
Как обнаружить Node2Shell
Клиенты Sysdig Secure, использующие управляемые политики, теперь имеют в своем распоряжении средства обнаружения и реагирования на Node2Shell. Запись в системе Threat Intelligence указывает на зоны риска, а правила среды выполнения (runtime rules) фиксируют эксплуатацию и последующие действия злоумышленника.
Аналитика угроз (Threat Intelligence)
В ленту Sysdig Threat Intelligence добавлена запись об уязвимости Node2Shell. В ней перечислены хосты и рабочие нагрузки, на которых запущены версии Node.js ниже исправленных релизов 26.12.1, 24.22.1 и 22.23.4, либо версии с завершенным сроком поддержки (EOL). Выберите количество хостов или рабочих нагрузок, чтобы открыть отфильтрованный поиск по затронутым активам.
Обнаружение на этапе выполнения (Runtime detection). Эксплуатация уязвимостей редко проходит чисто. Неудачные попытки приводят к аварийному завершению процесса Node.js, а собственная демонстрация компании Imperva потребовала нескольких попыток. Новое управляемое правило Node.js Process Crash Followed by In-Place Program Execution в политике Sysdig Runtime Behavioral Analytics сопоставляет аварийное завершение процесса Node.js с подозрительным выполнением программы, которое следует за ним в рамках той же рабочей нагрузки. Именно так выглядит цепочка эксплуатации уязвимости Node2Shell.
Если эксплойт срабатывает успешно, злоумышленник может выполнять команды от имени пользователя службы Node.js. Типичными дальнейшими шагами являются запуск интерактивной оболочки, загрузка вредоносного ПО, майнинг криптовалюты либо кража секретных данных и облачных токенов из контейнера. Управляемые политики, которые Sysdig Secure включает по умолчанию, уже выдают предупреждения о подобной активности. Клиенты защищены даже в том случае, если сам эксплойт остается незамеченным.
Как минимизировать риски Node2Shell
Исправление (Patch)
- Обновите Node.js до версий 22.23.4, 24.22.1 или 26.12.1. По заявлению Imperva, исправить декодер может только обновление Node.js.
- Обновите пакет Bun до версии 1.4.4 или новее везде, где он используется.
- Пересоберите образы контейнеров на основе исправленного базового слоя, а затем проверьте версию с помощью команды node --version в запущенном контейнере. Плавающий тег, такой как node:24, останется привязанным к старой версии, если вы выполняете пересборку из кеша, поэтому сначала запустите docker pull. Измените привязку в Dockerfile на версию 24.22.1 или более позднюю.
- Прежде чем полагаться на пакетные менеджеры, проверьте их. Менеджер Homebrew все еще распространял node 26.12.0, node@24 24.22.0 и node@22 22.23.3 спустя примерно 10 часов после релиза.
- Замените Node.js версии 20 и более старые на ветки 22.x или 24.x. Для старых версий исправления выпускаться не будут.
Снизьте доступность уязвимости на время применения патчей
- По возможности отключите декомпрессию запросов. В модуле body-parser инструкция express.json({ inflate: false }) отклоняет сжатые тела запросов с ошибкой 415. Сначала протестируйте свои клиенты. Это также приведет к отклонению запросов со сжатием gzip.
- Отклоняйте заголовок Content-Encoding: br для тел запросов на уровне прокси-сервера или балансировщика нагрузки в тех случаях, когда ваши клиенты его не отправляют. Компания Brandefense предлагает это как собственную рекомендацию, а не официальную инструкцию вендора. Протестируйте этот подход, прежде чем полагаться на него. Данная мера не распространяется на ответы, которые получают ваши сервисы.
- Проведите аудит вызовов fetch к серверам, которые вы не контролируете, а также любого прямого использования функции createBrotliDecompress().
- Настройте межсетевой экран веб-приложений (WAF), если он у вас есть. Imperva сообщает, что добавила правила WAF, и рекомендует ограничить несетевой трафик Brotli на затронутых путях. Рассматривайте это исключительно как дополнительный рубеж защиты, а не как полноценное исправление.
Ограничьте радиус потенциального ущерба
- Запускайте службы Node.js от имени непривилегированного пользователя и по возможности исключите хранение секретов в переменных окружения процесса. Выполнение кода происходит с правами процесса Node.js.
- Мониторьте веб-ориентированные процессы Node.js на предмет запуска командных оболочек и непредвиденных исходящих соединений.
Инвентаризация всей инфраструктуры
- Проведите инвентаризацию каждого экземпляра среды выполнения Node.js: контейнеров, агентов CI, бессерверных функций (serverless), серверов сборки и инструментов, которые поставляют собственный Node.js.
Заключение
Node2Shell — это ошибка не в каждой службе Node.js, а в тех сервисах, которые выполняют декодирование данных Brotli, полученных от потенциального злоумышленника. Фреймворк Express 5 с настройками парсинга JSON по умолчанию относит к этой группе большое количество экземпляров. На данный момент продемонстрированные последствия ограничиваются массовыми сбоями и выполнением кода в узком наборе конфигураций, поэтому порядок установки патчей должен определяться доступностью уязвимости (reachability).
Однако хронология событий служит серьезным предупреждением. В случае с Node2Shell публичный репозиторий, отслеживающий CVE, появился через пять часов после выпуска исправления, а рабочий PoC был опубликован в течение суток. Поскольку эта уязвимость кроется в нативной библиотеке, которую используют Node.js и другое ПО, каждый разработчик должен выпустить собственное исправление. Следовательно, специалистам по безопасности стоит ожидать обнаружения новых уязвимостей в нативных библиотеках под средами выполнения с сокращающимся интервалом времени.
Для команд безопасности текущая неделя должна начаться с инвентаризации, затем последует установка патчей в порядке доступности уязвимости, а для всего, что остается неисправленным, должен применяться принцип наименьших привилегий. Детектор в среде выполнения не увидит само переполнение буфера, но он зафиксирует последующие действия успешного эксплойта. Именно поэтому мониторинг поведения после взлома является той линией обороны, на которую стоит обратить внимание.









.png)
