26.10.2026 — CVE-2026-111497 (Broccoli2Shell, также Node2Shell) — запись за границы буфера в декодере Brotli с возможностью удаленного выполнения кода {#CVE-2026-111497}
Идентификатор CVE (CVE ID): CVE-2026-111497.
Ссылка на CVE: <https://www.cve.org/CVERecord?id=CVE-2026-111497>.
Ссылка на NVD: <https://nvd.nist.gov/vuln/detail/CVE-2026-111497>.
Исходный отчет {#original-report-CVE-2026-111497}
Информация об уязвимости и исправлении:
- Бюллетень Node.js — October 2026 Security Releases.
- Сайт уязвимости Broccoli2Shell.
- Исправляющий коммит в репозитории Brotli.
- GitHub Security Advisory — GHSA-9v8h-qqgm-4m35.
Краткое описание {#brief-description-CVE-2026-111497}
Brotli — алгоритм сжатия, который используется в HTTP (Content-Encoding: br), шрифтах WOFF2 и файловых форматах. Эталонная реализация Google на языке C встраивается в Node.js, .NET, пакеты Python Brotli и brotlicffi, Envoy, браузеры и поставляется дистрибутивами Linux как библиотека libbrotlidec.
Уязвимость находится в декодере (c/dec/decode.c): при обработке специально сформированного переключения типа блока (block switch) декодер записывает данные злоумышленника за границу внутреннего буфера. Это приводит к повреждению состояния декодера и соседней памяти: аварийному завершению процесса, раскрытию содержимого памяти и потенциально выполнению произвольного кода.
Эксплуатация не требует аутентификации. Достаточно, чтобы уязвимый процесс распаковал Brotli-поток, подготовленный злоумышленником. Основные пути атаки:
- Исходящие запросы.
fetch()в Node.js,HttpClientв .NET с включенным Brotli, клиенты Pythonrequests,urllib3,aiohttp,httpxпри установленном пакетеBrotliавтоматически распаковывают ответы сContent-Encoding: br. Вредоносный или скомпрометированный сервер атакует клиент: сервис, который обращается по пользовательским URL, обрабатывает вебхуки или опрашивает внешние API. - Входящие запросы. Express 5 и body-parser 2.x, ASP.NET Core с включенной распаковкой запросов (request decompression), Envoy с фильтром brotli decompressor распаковывают тела запросов с
Content-Encoding: br. Злоумышленник атакует сервер одним HTTP-запросом. - Прямой вызов декодера на недоверенных данных: архивах, сообщениях очередей, шрифтах, файлах пользователей.
Публичный PoC доступен с 22.10.2026. Выполнение кода продемонстрировано на немодифицированном официальном образе Node.js 24.22.0 (Linux arm64), но не при каждой попытке эксплуатации. На стандартных сборках с ASLR и NX надежно достигаются отказ в обслуживании и чтение памяти процесса. Данных об эксплуатации в реальных атаках на 26.10.2026 нет, в каталоге CISA KEV уязвимость отсутствует.
Встроенные копии декодера, синхронизированные с основной веткой Brotli после 27.02.2026, уже содержат исправление, даже если их релиз не упоминает CVE.
Затронутые технологии {#technologies-affected-CVE-2026-111497}
Уязвимость может присутствовать в каждой копии декодера Brotli на C. Проверять нужно все копии по отдельности:
- системную библиотеку
libbrotlidecи все продукты, которые ее используют:curl/libcurlс--compressed, пакеты дистрибутиваnodejsиpython3-brotli, браузеры; - встроенные (статически слинкованные) копии: Node.js, .NET, Envoy и Istio, PyPI-пакеты
Brotliиbrotlicffi, wheel-сборки, самодостаточные контейнеры; - образы контейнеров и виртуальных машин, собранные до выхода исправлений, включая образы Cloud Marketplace с Node.js, Python или .NET.
Независимые реализации декодера на Java, JavaScript, C# и Rust не содержат этого повреждения памяти.
Уязвимые продукты и версии {#vulnerable-products-and-versions-CVE-2026-111497}
Уязвимые версии и доступные исправления на 26.10.2026:
#| || Продукт | Уязвимые версии | Исправление || || Google Brotli (библиотека на C) | 1.0.3–1.0.9; 1.1.0; 1.2.0 | 1.0.10; 1.1.1; 1.2.1 || || Node.js | 22.x ниже 22.23.4; 24.x ниже 24.22.1; 26.x ниже 26.12.1. Ветки 20.x, 23.x, 25.x и старше не поддерживаются, исправлений для них нет | 22.23.4; 24.22.1; 26.12.1 || || PyPI Brotli | 1.0.3–1.2.0 | 1.2.1 || || PyPI brotlicffi | 1.0.3–1.2.0.2 | 1.2.1.0 || || .NET | 8.0 ниже 8.0.33; 9.0 ниже 9.0.22; 10.0 ниже 10.0.14; preview-версии 11.0 ниже 11.0.0-rc.3 | Runtime 8.0.33, 9.0.22, 10.0.14, 11.0.0-rc.3; SDK 8.0.133 / 8.0.427, 9.0.123 / 9.0.320, 10.0.114 / 10.0.403 || || Envoy | 1.36.11, 1.37.7, 1.38.5, 1.39.2 и более ранние версии этих веток | 1.36.12; 1.37.8; 1.38.6; 1.39.3; 1.40.0 || |#
Для пакетов дистрибутивов Linux сверяйтесь с бюллетенями безопасности дистрибутива: исправление может быть перенесено без изменения версии исходной библиотеки. Образы контейнеров проверяйте отдельно.
Разработчик {#vendor-CVE-2026-111497}
Google LLC.
Вектор атаки и уровень опасности согласно CVSS v.4.0 {#attack-vector-and-severity-level-CVE-2026-111497}
Базовая оценка: 9,2 CRITICAL.
Вектор атаки:
<code>CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N</code>
Оценка присвоена CNA (Google), оценки CVSS v.3.1 нет. Компонент AT:P (Attack Requirements: Present) означает, что для атаки нужно условие вне контроля злоумышленника: целевой процесс должен распаковать подконтрольные ему Brotli-данные.
Рекомендации по обнаружению уязвимости и дополнительные материалы {#recommendations-for-vulnerability-detection-CVE-2026-111497}
{% note warning %}
Номер версии библиотеки не подтверждает наличие исправления. Node.js не обновил встроенную библиотеку, а перенес только исправляющий коммит: process.versions.brotli показывает 1.1.0 в Node.js 22.23.4 и 1.2.0 в Node.js 24.22.1. Дистрибутивы переносят исправление в старые версии: исправленная libbrotlidec в Debian 12 остается версии 1.0.9. Поэтому проверяйте исправление по признакам ниже, а не по номеру версии библиотеки.
{% endnote %}
Найдите все копии декодера {#find-decoder-copies-CVE-2026-111497}
Проверьте системную библиотеку и пакеты:
<code>ldconfig -p | grep -i brotlidec
dpkg-query -W -f='${Package} ${Version}\n' 'libbrotli*' 2>/dev/null # Debian, Ubuntu
rpm -qa 'brotli*' 'libbrotli*' # RHEL, AlmaLinux
apk list -I 2>/dev/null | grep -i brotli # Alpine</code>
Найдите запущенные процессы, в которые загружен декодер — системная библиотека или модуль Python:
<code>sudo grep -l -E 'libbrotlidec|/_brotli' /proc/[0-9]*/maps 2>/dev/null | cut -d/ -f3 | xargs -r ps -o pid=,user=,comm= -p</code>
Команда не находит статически слинкованные копии. Node.js, .NET, Envoy и собственные сборки проверяйте отдельно по рекомендациям ниже.
Проверьте исправление по содержимому бинарного файла {#check-binary-CVE-2026-111497}
Исправление добавляет в декодер новый код ошибки BLOCKSWITCH, и его имя попадает в таблицу строк функции BrotliDecoderErrorString(). В ветке 1.0.x строка выглядит как BLOCKSWITCH, в ветках 1.1.x и 1.2.x — как ERRORFORMATBLOCKSWITCH. Поиск по подстроке BLOCKSWITCH покрывает оба случая. Контрольная строка EXUBERANTNIBBLE есть в таблице любой версии и показывает, что таблица присутствует в файле:
<code>for f in $(ldconfig -p | awk '/libbrotlidec/ {print $NF}'); do
echo "$f: BLOCK_SWITCH=$(grep -a -c BLOCK_SWITCH "$f") control=$(grep -a -c EXUBERANT_NIBBLE "$f")"
done</code>
BLOCKSWITCH больше нуля и control больше нуля — исправление есть; BLOCKSWITCH равно нулю при control больше нуля — библиотека уязвима; control равно нулю — метод неприменим, например для wheel-сборок PyPI-пакета Brotli. Для них используйте проверку для Python. Для крупных бинарных файлов, например Envoy, результат ориентировочный.
Проверьте Node.js {#check-nodejs-CVE-2026-111497}
Проверьте версию Node.js и наличие константы ошибки:
<code>node --version
node -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH"</code>
Исправленные сборки выводят -17, уязвимые — undefined: константа добавлена в node:zlib тем же релизом безопасности, что и исправление декодера. Для образов контейнеров выполните:
<code>docker run --rm --entrypoint node <образ> -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH"</code>
Если Node.js собран дистрибутивом с системной libbrotli, как в Ubuntu 22.04 и новее, решает состояние системной библиотеки. Проверьте, как слинкован бинарный файл, и при непустом выводе примените проверку бинарного файла:
<code>ldd "$(command -v node)" | grep -i brotli</code>
Проверьте Python {#check-python-CVE-2026-111497}
Проверьте установленные пакеты и версию декодера:
<code>python3 -m pip show Brotli brotlicffi 2>/dev/null | grep -E '^(Name|Version):' python3 -c "import brotli; print(brotli.__version__)"</code>
Для wheel-пакетов с PyPI brotli.version возвращает версию встроенного декодера: 1.2.1 означает исправленную сборку, 1.2.0 и ниже — уязвимую. Для пакета дистрибутива python3-brotli модуль линкуется с системной libbrotlidec и показывает ее версию, которая после переноса исправления не меняется. В этом случае используйте проверку бинарного файла. Если команда import brotli выполняется без ошибки, клиенты requests, urllib3, aiohttp и httpx в этом окружении автоматически распаковывают ответы Content-Encoding: br.
Проверьте .NET {#check-dotnet-CVE-2026-111497}
Проверьте установленные версии среды выполнения:
<code>dotnet --list-runtimes | grep Microsoft.NETCore.App</code>
Исправление содержат версии среды выполнения 8.0.33, 9.0.22, 10.0.14 и новее. Самодостаточные (self-contained) приложения пересоберите обновленным SDK. По умолчанию автоматическая распаковка Brotli в HttpClient и ASP.NET Core выключена.
Проверьте Envoy, Istio и curl {#check-envoy-istio-curl-CVE-2026-111497}
Проверьте версию Envoy, наличие фильтра распаковки в его конфигурации и поддержку Brotli в curl:
<code>envoy --version grep -rn 'brotli.decompressor' <каталог_конфигурации_envoy> curl -V | head -1</code>
Envoy уязвим только при настроенном фильтре brotli decompressor. Вывод curl -V содержит brotli/x.y.z, если libcurl собран с поддержкой Brotli. Номер берется из системной библиотеки во время выполнения и не отражает перенесенное исправление. libcurl распаковывает br только при включенной опции --compressed (CURLOPTACCEPTENCODING).
Проверьте процессы после обновления {#check-after-update-CVE-2026-111497}
Процессы продолжают использовать старую библиотеку до перезапуска. Найдите их:
<code>sudo grep -l 'libbrotlidec.*(deleted)' /proc/[0-9]*/maps 2>/dev/null | cut -d/ -f3 | xargs -r ps -o pid=,user=,comm= -p</code>
Пересоберите образы контейнеров с обновленными базовыми образами и повторно разверните сервисы. Обновление пакета на хосте не меняет копии декодера внутри образов.
Признаки попыток эксплуатации {#exploitation-indicators-CVE-2026-111497}
Обращайте внимание на следующие признаки:
- аварийные завершения процессов Node.js, Python, .NET, Envoy при распаковке данных (SIGSEGV, SIGABRT);
- ошибки декодера на исправленных сборках: в Node.js код ошибки
ERR_ERRORFORMATBLOCKSWITCHс двумя подчеркиваниями, вlibbrotliкод-17(BROTLIDECODERERRORFORMATBLOCK_SWITCH); - входящие запросы с
Content-Encoding: brна эндпоинты, которые не должны принимать сжатые тела.
Безопасная версия уязвимого продукта или патч {#safe-version-CVE-2026-111497}
Как можно скорее обновите уязвимые компоненты до версий из раздела Уязвимые продукты и версии, пакеты дистрибутивов — по бюллетеням дистрибутива. Если исправленного пакета дистрибутива еще нет, примените компенсационные меры, а Node.js и Python-пакеты обновите из апстрима.
После обновления перезапустите все процессы, использующие декодер, и пересоберите образы.
Компенсационные меры {#compensatory-measures-CVE-2026-111497}
{% note warning %}
Полностью устранить уязвимость можно только обновлением. Меры ниже сужают поверхность атаки, но не защищают прямые вызовы декодера на недоверенных данных. Для fetch() в Node.js обходного пути нет: ответ с Content-Encoding: br распаковывается независимо от того, был ли br заявлен в Accept-Encoding запроса, поэтому удаление br из заголовка не защищает от вредоносного сервера.
{% endnote %}
Входящие запросы {#incoming-requests-CVE-2026-111497}
Отклоняйте тела с Content-Encoding: br на входном прокси до передачи в приложение. Пример для nginx в контексте server или location:
<code>if ($http_content_encoding = "br") {
return 415;
}</code>
Сам nginx входящие тела не распаковывает, поэтому правило защищает только бэкенд за ним. Убедитесь, что бэкенд недоступен в обход прокси. Для Express 5 и body-parser 2.x отключите распаковку тел запросов. Парсеры будут отвечать кодом 415 на любые сжатые тела, включая gzip:
<code>app.use(express.json({ inflate: false }));
app.use(express.urlencoded({ extended: false, inflate: false }));</code>
В ASP.NET Core уберите провайдер br из настроек распаковки запросов. В Envoy отключите фильтр brotli decompressor.
Исходящие запросы {#outgoing-requests-CVE-2026-111497}
В Python удалите пакеты Brotli и brotlicffi, если приложение не вызывает их напрямую: requests, urllib3, aiohttp и httpx перестанут заявлять br и не будут пытаться распаковывать такие ответы.
<code>python3 -m pip uninstall -y Brotli brotlicffi</code>
В .NET исключите DecompressionMethods.Brotli из AutomaticDecompression обработчика HttpClient. В Node.js ограничьте исходящие запросы доверенными хостами. Сервисы, которые по заданию пользователя запрашивают произвольные URL или принимают вебхуки, обновляйте в первую очередь.
Общие меры {#general-measures-CVE-2026-111497}
Ограничьте сетевой доступ к сервисам, которые распаковывают Brotli от недоверенных сторон. Настройте лимиты памяти и автоматический перезапуск процессов, чтобы ограничить последствия отказа в обслуживании.
Защита с помощью Yandex Smart Web Security {#sws-protection-CVE-2026-111497}
Для приложений за Yandex Application Load Balancer добавьте в профиль безопасности базовое правило с действием «Запретить» по условию: заголовок Content-Encoding соответствует регулярному выражению .br.. Правило защищает только от входящих запросов.
Хронология раскрытия {#disclosure-timeline-CVE-2026-111497}
Хронология раскрытия уязвимости:
- 27.02.2026 — исправление принято в основную ветку репозитория Brotli без упоминания уязвимости;
- 21.10.2026 — выпущены Brotli 1.0.10, 1.1.1, 1.2.1 и Node.js 22.23.4, 24.22.1, 26.12.1;
- 22.10.2026 — опубликованы запись CVE и GitHub Security Advisory; появился публичный PoC;
- 23.10.2026 — опубликован бюллетень Envoy;
- 25.10.2026 — опубликован бюллетень .NET;
- 26.10.2026 — опубликован бюллетень Yandex Cloud.
Влияние на сервисы Yandex Cloud {#impact-on-yandex-cloud-services-CVE-2026-111497}
Критические сервисы и зависимости Yandex Cloud обновляются до версий с исправлением уязвимости. Продукты Yandex Cloud Marketplace находятся в процессе проверки и обновления.
Функции в сервисе Yandex Cloud Functions с предзагружаемой средой выполнения Node.js 22 получают исправление автоматически. Если предзагрузка отключена переменными окруженияXYCFNORUNTIMEPOOL, LDPRELOAD, LDLIBRARY_PATH или задан параметр --tmpfs-size, создайте новую версию функции. Функции на средах выполнения nodejs10–nodejs18 переведите на nodejs22.
Пользовательские сервисы, самостоятельно развернутые на виртуальных машинах, в контейнерах, в Yandex Managed Service for Kubernetes, в собственных образах или из Cloud Marketplace, автоматически не обновляются и требуют проверки со стороны владельцев по разделу Рекомендации по обнаружению уязвимости.