TL;DR

⚠️ Brotli — популярная библиотека сжатия от Google. 21 октября Node.js раскрыл CVE-2026-111497 («node2shell»), уязвимость в декодере Brotli, которая позволяет процессу Node.js при распаковке контролируемых атакующим данных утечь память или выполнить произвольный код. 22 октября Python опубликовал обновление безопасности, закрывающее ту же уязвимость. Дальше выяснилось, что CVE-2026-111497 затрагивает и другие основные языки и приложения, использующие HTTP, — патчи для них доступны не везде.

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

Обновление 4:12 PM PT: патчи доступны для libbrotli, Python, C++, NodeJS, Bun, Envoy и других. Apache и Nginx по умолчанию не декодируют Brotli.

Обновление 4:15 PM PT: OpenAI поделилась, что обнаружила уязвимость в феврале. Корневая причина была исправлена в исходном коде Brotli в то время, но это не было признано уязвимостью безопасности. Советы OpenAI здесь.

Node.js Brotli уязвимость

Что такое Brotli?

Brotli — алгоритм сжатия без потерь и формат данных, разработанный Google. Это способ уменьшить размер данных для хранения или отправки через интернет. Программное обеспечение затем распаковывает его, чтобы восстановить исходные данные. Широко используется для сжатия HTTP, чтобы упаковать веб-контент вроде HTML, CSS и JavaScript.

Что такое CVE-2026-111497?

CVE-2026-111497 — выход за границы при записи в декодере Google Brotli, затрагивающий версии 1.0.3–1.2.0 на всех платформах. Это та же уязвимость в декодере Brotli, которая стоит за Node2Shell. Удалённый, не прошедший аутентификацию злоумышленник может отправить потоковую обработку Brotli специального формата, чтобы повредить память, утечь конфиденциальные данные, упасть процессу или потенциально выполнить произвольный код. CVSS v4.0 оценивает её как 9.2 (критическая), и Node.js уязвим через встроенную библиотеку Brotli.

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

OpenAI обнаружила это в феврале и сообщила о выполнении произвольного кода без аутентификации, работающем в обе стороны: вредоносный клиент может захватить непатченный сервер, а вредоносный сервер может захватить непатченного клиента, который принимает сжатые ответы.

Корневая причина была исправлена в исходном коде Brotli в феврале, но это не было признано проблемой безопасности в то время, и никакой релиз не был выпущен с исправлением до сих пор. Это означает, что каждый проект, который включает Brotli, должен выпустить своё обновление.

Вы подвергаетесь риску, если какая-то среда имеет установленным Brotli 1.2.0 или более ранний, или brotlicffi 1.2.0.x, так как HTTP-клиенты вроде requests, httpx и aiohttp загружают эти пакеты автоматически, когда они присутствуют. Обновитесь до Brotli 1.2.1 или brotlicffi 1.2.1.0 и пересоберите любые образы контейнеров, которые их включают. На 23 октября базы данных рекомендаций не сопоставляют CVE ни с одним пакетом PyPI, поэтому pip-audit, Dependabot и Safety пока не помечают уязвимые версии.

Отслеживаемое здесь в Aikido Intel:

Что касается не уязвимого ПО: стандартный модуль Apache mod_brotli не декодирует Brotli.

Как запатчить HTTP2Shell CVE-2026-111497

Для CVE-2026-111497 обновите уязвимую среду выполнения или библиотеку Brotli:

  • Node.js: обновитесь до 22.23.4, 24.22.1 или 26.12.1, либо более новой поддерживаемой версии в соответствующей ветви релиза.
  • Native Brotli / libbrotli: обновитесь до 1.2.1 или позже. Для более старых веток релиза используйте патченные 1.0.10 или 1.1.1.
  • Python пакеты: обновите Brotli до 1.2.1 или позже и brotlicffi до 1.2.1.0 или позже, где установлены.
  • curl / libcurl: обновите зависимость Brotli до 1.2.1, патченного более старого релиза или пакета безопасности вендора. Встроенные или статически связанные копии требуют обновления сборки приложения.
  • Bun: обновитесь до 1.4.4 или позже. Пересоберите скомпилированные исполняемые файлы, которые включают Bun.
  • Envoy: обновитесь до 1.40.0, 1.39.3, 1.38.6 или 1.37.8, либо более новой версии в поддерживаемой ветви. 1.36.12 также включает исправление, но ветвь 1.36 не поддерживается.
  • Istio: исправление включено в 1.29.9, 1.30.6 и 1.31.2. Используйте более новую поддерживаемую версию в соответствующей ветви; ветвь 1.29 достигла конца жизни.
  • Пакеты операционной системы: установите обновление безопасности вендора. Поставщики могут перенести исправление без изменения номера версии вверх по течению.
  • Другие HTTP-серверы, обратные прокси, API-шлюзы и HTTP-клиенты: обновите используемую ими среду выполнения или библиотеку Brotli. Где Brotli встроена в продукт, установите версию производителя продукта, которая явно закрывает этот CVE. Для управляемых сервисов подтвердите исправление у провайдера.

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

Исправленные версии, проверено 23 октября 2026
Проект Статус патча Исправленные версии Примечания
Node.js Патч доступен 22.23.4 · 24.22.1 · 26.12.1 Используйте поддерживаемую ветвь релиза.
Bun Патч доступен 1.4.4 Включает Brotli 1.2.1.
Envoy Патч доступен 1.40.0 · 1.39.3 · 1.38.6 · 1.37.8 1.36.12 также включает исправление, но 1.36 не поддерживается. Используйте поддерживаемую ветвь.
Istio Патч доступен 1.29.9 · 1.30.6 · 1.31.2 1.29 достигла конца жизни, поэтому перейдите на поддерживаемую ветвь.
Google Brotli (upstream) Патч доступен 1.0.10 · 1.1.1 · 1.2.1 Выберите исправленный релиз для вашей ветви библиотеки.

Что делать, если вы не можете обновиться прямо сейчас

Эти обходные пути снижают риск, пока вы готовите обновление:

  • Приложения на Python: где поддержка Brotli опциональна, удалите оба пакета Brotli и brotlicffi из затронутых окружений. Удалите зависимые доп. возможности вроде httpx[brotli] и любые другие требования, которые переустановили бы их, затем пересгенерируйте блокировки зависимостей и пересоберите/перезагрузите нагрузки. HTTPX, Requests и urllib3 сохраняют поддержку gzip и deflate без этих опциональных пакетов. Однако сервер, который отправляет Brotli, может всё равно создать нечитаемый ответ или ошибку приложения; автоматическая откат не гарантирован.
    • Удаление обоих пакетов Python и перезагрузка нагрузок удаляет пути декодирования, предоставленные этими пакетами для входящих и исходящих данных. Это не удаляет отдельные декодеры Brotli, встроенные в другие среды выполнения, библиотеки или продукты.
  • Входящие HTTP-запросы: отклоняйте запросы, чьё Content-Encoding включает br на обратном прокси, балансировщике нагрузки или промежуточном ПО приложения, перед тем как любой уязвимый декодер обработает тело. Сопоставляйте br без учёта регистра, включая внутри списков кодирований.
  • Исходящие HTTP-запросы: удалите br из Accept-Encoding. Также отключите декодирование ответа Brotli или отклоняйте ответы, чьё Content-Encoding включает br перед началом декодирования. Убедитесь, что эта проверка происходит перед автоматической обработкой тела; проверка после того, как клиент загрузил и декодировал ответ, уже поздно.

Изменение одного Accept-Encoding недостаточно: вредоносный сервер может отправить ответ Brotli независимо от того, что объявляет клиент, и urllib3 выбирает декодер из заголовка Content-Encoding ответа.

Держите эти контроли на месте, пока затронутые компоненты не будут патчены и проверены. Просмотрите охват, когда поставщики подтвердят дополнительные затронутые компоненты или векторы атак.

Как Aikido помогает с CVE-2026-111497

Aikido помечает уязвимые версии Brotli и brotlicffi в ваших репозиториях, образах контейнеров и зависимостях, включая когда они приходят как транзитивные зависимости. Ваша панель показывает, какие сервисы всё ещё работают с уязвимой версией, поэтому вы можете обновить сначала те, которые вызывают внешние серверы или принимают сжатые тела запросов.

После обновления Aikido проверит, что находка исчезла.

Временная шкала

Brotli — популярная библиотека сжатия от Google. 21 октября Node.js раскрыл CVE-2026-111497, прозванный «node2shell», в котором процесс Node.js, распаковывающий контролируемые атакующим данные Brotli, может быть заставлен утечь память или выполнить произвольный код. Пользователи были подверганы риску, если их приложение или библиотека распаковывает повреждённые данные Brotli (напр. встроенный fetch(), body-parser).

В следующий день Python выпустил обновление безопасности, которое закрывает ту же ошибку; пакеты Python также были уязвимы для CVE-2026-111497. Уязвимость Brotli может затронуть и другие языки и приложения сервисов, учитывая, как широко интегрирована библиотека вниз по течению. Оказывается, OpenAI нашла это ещё в феврале.

Технические детали CVE-2026-111497

Ошибка находится в DecodeBlockTypeAndLength(), которая обрабатывает переключения блоков — точки, где поток Brotli переключается с одного дерева Huffman на другое. В уязвимых версиях функция возвращает простое boolean, и BROTLI_FALSE может означать либо «этот поток неправильный», либо «мне нужно больше входных данных». Вызывающие не могут различить эти два варианта, и на быстром пути декодер полностью игнорирует возвращаемое значение.

Специально созданный поток может объявить один тип блока, а затем исчерпать длину этого блока, что вынуждает переключение, которое не может быть выполнено. Декодер затем либо сообщает, что ему нужно больше входных данных для потока, который завершён, либо продолжает декодировать с уже имеющимся состоянием блока. Этот второй путь приводит к выходу за границы при записи.

Исправление вверх по течению, google/brotli commit 0ed4268, заставляет функцию возвращать код ошибки и добавляет новую ошибку, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (-17). Декодирование теперь останавливается на ошибке формата на обоих безопасном и быстром путях. OSM сравнил исходные дистрибутивы Brotli 1.2.0 и 1.2.1 и нашел, что 1.2.1 отличается только приращением версии и изменениями декодера из этого commit'а.

Уязвимость Brotli в библиотеках Python (CVE-2026-111497)

Ошибка Brotli, стоящая за Node2Shell (CVE-2026-111497), затрагивает Python. Два пакета PyPI, Brotli и brotlicffi, компилируют один и тот же уязвимый декодер Brotli, который объединяет Node.js. Официальное рекомендация было опубликовано на GitHub. Brotli имеет 82,8 миллиона загрузок в месяц.

Вы затронуты, если какая-то Python окружение, в которой вы работаете, имеет установленным Brotli 1.2.0 или более ранний, или brotlicffi 1.2.0.x. Популярные HTTP-клиенты вроде requests и httpx загружают эти пакеты автоматически когда они присутствуют. Некоторые пакеты автоматически устанавливают Brotli как зависимость вроде Scrapy, в то время как другие требуют явного упоминания. Злоумышленник может достичь уязвимого декодера, отправив вредоносный ответ Brotli на запрос, который делает ваше приложение, или отправив телом запроса вашему приложению данные, сжатые Brotli. Это означает, что приложение может быть подвергнуто риску без импорта Brotli где-либо в его собственном коде. Это популярная транзитивная зависимость, поэтому проверьте ваши системы.

Чтобы это исправить, обновитесь до патченных релизов:

  • Brotli → 1.2.1
  • brotlicffi → 1.2.1.0

Примечания релиза обеих исправленных версий не упоминают CVE. На 23 октября базы данных рекомендаций не сопоставляют его ни с одним пакетом PyPI, поэтому pip-audit, Dependabot и Safety пока не помечают эти версии.

Кто затронут CVE-2026-111497 в Python?

Вы затронуты, если какое-либо из ваших Python окружений имеет установленным один из этих пакетов:

Пакет Уязвимые версии Исправленная версия
Brotli (PyPI) 1.2.0 и более ранние 1.2.1
brotlicffi (PyPI) 1.2.0.x 1.2.1.0

Ваш код не должен импортировать ни один из этих пакетов. Эти HTTP-клиенты объявляют Accept-Encoding: br и автоматически декодируют ответы Brotli:

  • urllib3 (и поэтому requests) когда установлены Brotli или brotlicffi
  • httpx с extra brotli
  • aiohttp когда установлен Brotli
  • Scrapy и всё, что построено на клиентах выше

Данные атакующего могут достичь декодера двумя путями:

  • Исходящие запросы. Ваше приложение выбирает ответ Brotli с сервера, который контролирует атакующий, например через доставку webhook, предпросмотр URL, краулер или функцию «выбрать этот URL».
  • Входящие запросы. Ваша фреймворк или промежуточное ПО декодирует тело запроса, отправленного с Content-Encoding: br, что является Python эквивалентом случая Express 5 в Node.js.

Как исправить CVE-2026-111497 в Python

Исправление — это обновление пакета, и оно занимает четыре шага:

  1. Обновите какой бы пакет вы ни имели установленным с помощью pip install -U "Brotli>=1.2.1" или pip install -U "brotlicffi>=1.2.1.0". Если вы используете файл блокировки с Poetry, uv или pip-tools, обновите ограничение и пересгенерируйте файл блокировки.
  2. Пересоберите ваши образы контейнеров и любые wheels, которые объединяют оба пакета. Образ, построенный на уязвимой версии, остаётся уязвимым, пока вы его не пересоберёте.
  3. Проверьте каждое окружение, которое вы запускаете, включая ноутбуки, CI-бегуны, серверы и контейнеры. Многие проекты вытягивают Brotli через HTTP-клиент extra, поэтому смотрите на вашу полную разрешённую дерево зависимостей.
  4. Полагайтесь на ручную проверку пока. pip-audit, Dependabot и Safety не будут сообщать об этом, пока базы данных рекомендаций не сопоставят CVE с пакетами PyPI.

Если ваши Python привязки Brotli пришли из пакета дистрибутива Linux вместо PyPI, исправление приходит через вашу дистрибуцию, поэтому проверьте его рекомендацию безопасности также.

Что такое уязвимость Python Brotli (CVE-2026-111497)?

Уязвимость Python Brotli относится к CVE-2026-111497, ошибке декодера Brotli, известной как Node2Shell, поскольку она затрагивает пакеты Python на PyPI. Запись CVE связывает CWE-252 (непроверенное возвращаемое значение) с CWE-787 (выход за границы при записи).

Насколько серьёзна CVE-2026-111497 для Python и используется ли она?

Запись CVE присваивает ошибке оценку CVSS 4.0 в 9.2, и Node.js оценивает её как высокую серьёзность. OSM собрал Brotli 1.2.0 и 1.2.1 с AddressSanitizer и запустил специально созданный поток через обе версии. Версия 1.2.0 потребляла весь приблизительно 23 МБ поток и продолжала сообщать, что ей нужно больше входных данных, независимо от того, прибыл ли поток целиком или в кусочках размером всего один байт. Версия 1.2.1 отклонила поток с ошибкой -17 каждый раз.

OSM не преследовал коррупцию памяти или выполнение кода в расширении Python. Код декодера — это тот же код, который исследователи эксплуатировали против немодифицированной сборки Node.js 24.22.0, как сообщали Imperva и другие. Для Node.js The Hacker News сообщил об отсутствии эксплуатации в дикой природе по состоянию на 22 октября.

Относитесь к этому как срочному в любом случае. Ошибка — ошибка безопасности памяти в компоненте, который обрабатывает недоверённые входные данные сети, и исправление — это рутинное обновление версии. Сервисы, которые вызывают внешние серверы или принимают сжатые тела запросов, должны пойти первыми.

Как проверить, подвергнуто ли ваше приложение Python риску

  1. Проверьте установленные версии с помощью pip show Brotli brotlicffi в каждом окружении и с помощью docker run --rm <image> pip show Brotli brotlicffi для каждого образа контейнера.
  2. Найдите, что вытягивает пакеты. Запустите pipdeptree -r -p Brotli, чтобы увидеть, какие зависимости требуют его, и просмотрите ваши файлы блокировки с помощью grep -i brotli poetry.lock uv.lock requirements*.txt.
  3. Перечислите исходящие HTTP-вызовы, которые идут на серверы, которые вы не контролируете, и любые конечные точки, которые декодируют тела запросов Content-Encoding: br.
  4. Обновите сервисы, которые совпадают с шагом 3 первыми, затем остальные.

Если вы воспроизводите ошибку из Python, brotli.decompress() повышает общую brotli.error: decoder failed для любой ошибки, поэтому вы не можете увидеть, какой код ошибки сработал. Decompressor(), которому передан специально созданный поток пошагово, никогда не завершится на 1.2.0.

FAQ

Какие версии исправляют CVE-2026-111497 в Python?

Brotli 1.2.1 и brotlicffi 1.2.1.0, наряду с любыми более новыми релизами.

Нужно ли мне импортировать Brotli в мой код, чтобы быть затронутым?

Установленного пакета достаточно. urllib3, requests, httpx и aiohttp используют Brotli или brotlicffi автоматически, когда любой присутствует, и декодируют ответы Brotli с любого сервера, который вызывает ваше приложение.

Помечает ли pip-audit или Dependabot это?

Нет пока. На 23 октября запись CVE, OSV и GitHub Advisory Database не перечисляют ни один пакет PyPI. OSM отправляет записи PYSEC и сопоставление пакета PyPI для рекомендации GitHub, чтобы инструмент это подхватил.

Есть ли обходной путь?

Удаление Brotli и brotlicffi удаляет уязвимый декодер, и HTTP-клиенты откатываются на gzip и deflate. Отклонение запросов, кодированных Brotli, на краю снижает входящую подверженность риску, но не защищает от ответов Brotli, которые выбирает ваше приложение.