1

Sua stack usa Brotli e você provavelmente não sabe — o que o HTTP2Shell ensina sobre dependências invisíveis

A CVE-2026-111497 — apelidada de HTTP2Shell — é uma falha crítica (9.2/10) na Brotli, a biblioteca de compressão que está em praticamente toda a web. Node.js, Python e .NET afetados de uma vez, e a CISA confirmou exploração ativa.

Mas este artigo não é sobre a CVE. É sobre a pergunta que ela escancarou e que quase nenhum time sabe responder:

Você sabe se a sua aplicação usa Brotli?

A maioria descobre que sim — do pior jeito. Porque a Brotli quase nunca aparece no package.json, no requirements.txt ou no .csproj. Ela entra como dependência da dependência: o framework HTTP puxa, o cliente de rede puxa, o runtime embute. Invisível no inventário.

O problema real: atualizar só resolve se você souber onde a falha mora

Quando sai uma CVE crítica, a corrida é "aplicar o patch". Mas patch pressupõe três respostas que o time precisa ter antes do incidente:

  1. Onde isso roda? Quais serviços, quais versões, qual exposição (borda pública ou job interno)?
  2. Quem puxa isso? Direto ou transitivo? Se é transitivo, qual dependência direta precisa subir de versão?
  3. O que me avisa? Se a resposta é "o noticiário", o processo já falhou.

No caso da Brotli, os patches existiam: Microsoft, Google, Node e Python publicaram correções rápido. O que separa quem resolveu em horas de quem vai descobrir pelo incidente não é ferramenta — é processo de inventário.

Como responder "onde mora?" na prática

Para enxergar a árvore transitiva da sua stack, hoje, sem instalar nada:

# Node
npm ls brotli --all        # ou: npm ls zlib (bindings nativos ficam no core)

# Python
pip install pipdeptree && pipdeptree --reverse --packages brotli

# .NET
dotnet list package --include-transitive | grep -i brotli

Atenção ao detalhe cruel do caso: parte do risco não está nem em pacote instalável, mas em binding nativo embutido no runtime (o zlib/brotli do próprio Node, por exemplo). Ou seja: a correção pode ser subir a versão do runtime, não de um pacote. Inventário que só olha o lockfile não enxerga isso.

O mínimo viável de gestão de dependências

Não precisa de plataforma cara para sair do zero:

  • SBOM gerado no CI (Syft, CycloneDX, npm sbom): um artefato por build dizendo o que entrou. Quando a próxima CVE sair, a pergunta "onde mora?" vira um grep.
  • Lockfile sempre commitado e builds reproduzíveis — sem isso, o SBOM mente.
  • Renovate/Dependabot com janela de atualização regular. Atualização adiada é porta aberta com hora marcada — foi exatamente assim que dezenas de lojas brasileiras acabaram com skimmer no checkout semanas atrás (a correção existia havia 5 meses).
  • Priorização por exposição: CVE crítica em serviço de borda pública ≠ mesma CVE num worker interno. Severidade sem contexto gera fila infinita; contexto gera decisão.

A lição

Segurança não é evento, é processo: inventário contínuo, monitoramento e capacidade de resposta. A próxima Brotli vai sair — a única escolha é descobrir pelo seu pipeline ou pelo seu incidente.

Pergunta para a comunidade: seu time consegue responder "onde roda a lib X?" em menos de 10 minutos? Como vocês resolveram — SBOM, scanner, planilha na raça?


Escrevo a série segurança sem hype — o golpe do momento explicado antes de você cair nele.

Carregando publicação patrocinada...