Node.js e a falha do Brotli (CVE-2026-111497): como saber se a sua aplicação está exposta e como corrigir

Em 21 de outubro de 2026 o Node.js corrigiu uma escrita fora dos limites no seu decodificador Brotli que já é explorada. Que versões corrigem, quem está realmente exposto, um verificador de versões e as outras nove vulnerabilidades da mesma versão.

Neste artigo
Em 30 segundos

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.jsVersão corrigidaEstado
26.x26.12.1Com suporte
24.x24.22.1Com suporte
22.x22.23.4Com suporte
20.x, 23.x e 25.xNenhumaSem 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.

bash
# 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 .
Comandos de referência; este guia não os executa porque dependem do seu servidor.
javascript
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"));
Imprime o estado de oito versões (22.23.3, 24.22.0 e 26.12.0 vulneráveis; 22.23.4, 24.22.1 e 26.13.0 corrigidas; 20.19.0 e 25.1.0 sem correção) e depois 1 1 0 0: dois usos do decodificador, nenhum de compressão nem de outros caminhos.

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.

CVEGravidadeComponenteO que acontece
CVE-2026-111497AltaDecodificador Brotli do node:zlibEscrita fora dos limites com dados malformados: queda, vazamento de memória ou execução de código
CVE-2026-105482AltaDNS (dns.resolve*, dns.reverse)Bytes NUL em nomes de host são truncados em silêncio
CVE-2026-105483AltaVerificação de host TLSIP com dígitos de largura total não é reconhecido como IP (26.x e 24.x)
CVE-2026-106069AltaVerificação de host TLSIPv4 com zeros à esquerda é lido de forma diferente do resolvedor do sistema
CVE-2026-105481MédiaKeep-alive do agente HTTPUma resposta recebida antes de enviar a requisição pode ser aceita como a da nova
CVE-2026-106072MédiaVerificação de host TLSFormas não canônicas de IPv4 permitem que um SAN DNS autentique um endpoint IP
CVE-2026-106074Médiacrypto.randomUUID(), randomUUIDv7(), randomInt()Snapshots e SEA repetem os mesmos valores em cada processo
CVE-2026-106070Baixazlib.ZipFile (só 26.x)Após um cabeçalho inválido, uma leitura posterior pode devolver bytes do atacante
CVE-2026-106071BaixaModelo de permissões (só 26.x)Curingas como /etc/passwd.* também concedem /etc/passwd
CVE-2026-106073BaixaModelo 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.

Compare estas opções

Compare opções de nuvem

Confira preços, limites, condições e fontes de cada opção.

Abrir comparador
Consultoria

Seu caso é diferente?

Conte seu contexto e as opções que você está avaliando. Respondemos com critérios e fontes, sem assinaturas automáticas.

Pedir consultoria