O decodificador Brotli do node:zlib tinha uma escrita fora dos limites que permite queda, vazamento de memória ou execução de código com dados malformados; as versões corrigidas são 26.12.1, 24.22.1 e 22.23.4, as linhas 20, 23 e 25 não têm correção, e a falha já está no catálogo de vulnerabilidades exploradas da CISA.
1. O que aconteceu#
Em 21 de outubro de 2026 o projeto Node.js publicou versões de segurança para as suas linhas 22, 24 e 26. A mais grave das dez vulnerabilidades corrigidas é a CVE-2026-111497, uma escrita fora dos limites no decodificador Brotli do node:zlib. O projeto a classifica como alta; o Google, como autoridade de numeração, a pontua com 9,2 (crítica) no CVSS v4.0, segundo a Rapid7. A imprensa a batizou de Node2Shell ou Broccoli2Shell.
| Linha do Node.js | Versão corrigida | Estado |
|---|---|---|
| 26.x | 26.12.1 | Com suporte |
| 24.x | 24.22.1 | Com suporte |
| 22.x | 22.23.4 | Com suporte |
| 20.x, 23.x e 25.x | Nenhuma | Sem suporte: afetadas e sem correção; é preciso migrar |
Não é só teoria. Segundo o Help Net Security, há exploits públicos no GitHub, a Imperva demonstrou execução de código contra a imagem oficial do Node.js 24.22.0 para Linux arm64 e a ELLIO vê tráfego de exploração real. A Rapid7 informa que a CISA adicionou a falha ao seu catálogo de vulnerabilidades exploradas em 27 de outubro.
Documentação: Node.js: versões de segurança de 21 de outubro de 2026 (inglês) ↗
2. Como a falha funciona#
O decodificador trata uma troca de bloco inválida como uma necessidade temporária de mais dados e não como um erro de formato permanente. Então continua acrescentando dados a um buffer interno de 8 bytes e escreve além dos seus limites. Para dispará-la, um atacante precisa conseguir que a sua aplicação descomprima com node:zlib dados Brotli que ele controla.
Esta precisão importa: a página do Node.js só nomeia o node:zlib. Não diz se o tratamento HTTP de Content-Encoding: br nem o fetch são afetados, então não dê isso por certo. E segundo a Rapid7, o decodificador existir no seu ambiente não confirma a exposição: é preciso um caminho que processe dados comprimidos controlados por um atacante.
Documentação: Rapid7: CVE-2026-111497, escrita fora dos limites no decodificador Brotli do Node.js (inglês) ↗
3. Quem é afetado#
Afeta as linhas 26.x, 24.x e 22.x anteriores às versões corrigidas. As linhas 20.x, 23.x e 25.x, que já não têm suporte, também são afetadas e não receberão correção, segundo o Help Net Security.
O problema nasce na biblioteca Brotli do Google, então não é só do Node.js. A Tenable, citada pelo Help Net Security, inclui .NET, Bun, Envoy, Istio, clientes HTTP de Python, FFmpeg, Apache Arrow e ClickHouse. As versões afetadas e a exposição padrão variam: revise o aviso de cada provedor. A biblioteca corrigida é a 1.2.1, a 1.1.1 ou a 1.0.10 conforme o ramo.
Documentação: Help Net Security: a falha do Brotli vai além do Node.js (inglês) ↗ · Node.js: calendário de versões (inglês) ↗
4. Como saber se você está afetado#
Primeiro a versão: a que roda de verdade, não a do seu terminal. Em contêineres, a imagem que está implantada. O script compara uma versão com as corrigidas e procura no seu código os usos do decodificador Brotli, que é a parte vulnerável.
# A versão do Node que realmente roda: no servidor, no contêiner e no CI
node -v
docker ps --format "{{.Names}} {{.Image}}"
docker exec NOME node -v
# Depois de atualizar: reconstrua a imagem (com uma tag móvel como node:22-alpine, baixe a base nova)
docker build --pull --no-cache -t meu-app .const FIXED = { 22: [22, 23, 4], 24: [24, 22, 1], 26: [26, 12, 1] }; // primeira versão corrigida por linha
const parse = version => String(version).replace(/^v/, "").split(".").map(Number);
function status(version) {
const [major, minor, patch] = parse(version);
const fixed = FIXED[major];
if (!fixed) return major > 26 ? "linha mais nova que as corrigidas: revise o aviso" : "SEM CORREÇÃO: linha sem suporte; migre para 22, 24 ou 26";
const [, fixedMinor, fixedPatch] = fixed;
const ok = minor > fixedMinor || (minor === fixedMinor && patch >= fixedPatch);
return ok ? "corrigida" : `VULNERAVEL: atualize para ${fixed.join(".")}`;
}
// Procure no seu código o decodificador Brotli do node:zlib (a compressão não é a parte vulnerável)
const BROTLI_DECODER = /\b(?:createBrotliDecompress|brotliDecompress(?:Sync)?)\b/g;
const usesBrotli = code => (code.match(BROTLI_DECODER) ?? []).length;
for (const v of ["v22.23.3", "v22.23.4", "v24.22.0", "v24.22.1", "v26.12.0", "v26.13.0", "v20.19.0", "v25.1.0"]) console.log(v, "->", status(v));
console.log(usesBrotli("zlib.brotliDecompressSync(body)"), usesBrotli('const { createBrotliDecompress } = require("node:zlib")'), usesBrotli("zlib.brotliCompressSync(body)"), usesBrotli("gzip"));Um resultado diferente de zero na busca não significa que você tem um problema: significa que deve verificar se esse caminho recebe dados de usuários ou de servidores que você não controla.
5. Como corrigir#
- Atualize para a 26.12.1, 24.22.1 ou 22.23.4 conforme a sua linha.
- Reconstrua as imagens de contêiner a partir da base nova e implante de novo. Se usa uma tag móvel como node:22-alpine, force o download (docker build --pull) e confirme a versão dentro do contêiner.
- Reinicie os serviços: um processo que já está rodando continua com a versão antiga.
- Revise os pacotes que trazem o seu próprio Brotli: Bun, os pacotes brotli e brotlicffi do Python, .NET, Envoy ou Istio, conforme o caso.
- Se está na 20.x, 23.x ou 25.x, planeje a migração para uma linha com suporte; não haverá correção.
Na Codifly, o site roda no Node.js 22.23.4, que já inclui a correção: verificamos dentro do contêiner de produção.
6. Se você não pode corrigir hoje#
O Node.js não publicou nenhuma solução alternativa: a sua única indicação é atualizar. A Rapid7 sugere, como medida temporária, restringir ou desativar os caminhos da aplicação que descomprimem Brotli de origem não confiável.
Como critério próprio, não dos avisos: veja onde a sua aplicação aceita corpos ou arquivos comprimidos e limite quem pode enviá-los enquanto atualiza.
7. As outras nove vulnerabilidades da mesma versão#
A versão de 21 de outubro corrige dez vulnerabilidades. A tabela as resume segundo a página do Node.js; se você usa verificação TLS contra endereços IP, resolução DNS com nomes fornecidos por usuários ou o modelo de permissões, leia-as também.
| CVE | Gravidade | Componente | O que acontece |
|---|---|---|---|
| CVE-2026-111497 | Alta | Decodificador Brotli do node:zlib | Escrita fora dos limites com dados malformados: queda, vazamento de memória ou execução de código |
| CVE-2026-105482 | Alta | DNS (dns.resolve*, dns.reverse) | Bytes NUL em nomes de host são truncados em silêncio |
| CVE-2026-105483 | Alta | Verificação de host TLS | IP com dígitos de largura total não é reconhecido como IP (26.x e 24.x) |
| CVE-2026-106069 | Alta | Verificação de host TLS | IPv4 com zeros à esquerda é lido de forma diferente do resolvedor do sistema |
| CVE-2026-105481 | Média | Keep-alive do agente HTTP | Uma resposta recebida antes de enviar a requisição pode ser aceita como a da nova |
| CVE-2026-106072 | Média | Verificação de host TLS | Formas não canônicas de IPv4 permitem que um SAN DNS autentique um endpoint IP |
| CVE-2026-106074 | Média | crypto.randomUUID(), randomUUIDv7(), randomInt() | Snapshots e SEA repetem os mesmos valores em cada processo |
| CVE-2026-106070 | Baixa | zlib.ZipFile (só 26.x) | Após um cabeçalho inválido, uma leitura posterior pode devolver bytes do atacante |
| CVE-2026-106071 | Baixa | Modelo de permissões (só 26.x) | Curingas como /etc/passwd.* também concedem /etc/passwd |
| CVE-2026-106073 | Baixa | Modelo de permissões, fs.realpathSync() | Permite sondar caminhos fora dos diretórios permitidos |
8. Mantenha seus números em dia#
As versões e os identificadores são os publicados até 28 de outubro de 2026. A exploração avança rápido: revise de novo o aviso do Node.js e o catálogo da CISA.
- Assine a lista nodejs-sec.
- Mantenha um inventário da versão do Node.js de cada serviço e imagem.
- Automatize um alerta quando uma versão ficar abaixo da corrigida.
Fontes e escopo
Documentação consultada em 28 de outubro de 2026. Os exemplos e critérios de decisão são propostas editoriais; adapte-os ao contrato da sua aplicação e valide-os no seu ambiente de testes autorizado.