O scan diário de vulnerabilidades das nossas imagens de produção apontou uma falha crítica na imagem da Evolution API: a CVE-2026-41242, no protobufjs, com nota 9.8 no NVD. O detalhe que torna o caso interessante: a cópia principal do pacote já estava corrigida. A versão vulnerável estava escondida dentro de outra dependência, e o projeto não tem release estável nova desde a 2.3.7, de dezembro de 2025. Neste artigo mostramos como encontramos essa cópia, por que "atualizar a imagem" não era opção e o passo a passo que usamos para corrigir sem quebrar o WhatsApp.
O que é a CVE-2026-41242
O protobufjs é a implementação de Protocol Buffers mais usada no ecossistema JavaScript. A falha (CWE-94, injeção de código) acontece quando a biblioteca carrega uma definição de protobuf ou um descritor JSON montado por um atacante: nomes e referências de tipo controlados pelo esquema chegam à geração de código em tempo de execução sem validação suficiente, e isso permite executar JavaScript arbitrário no processo.
- Severidade: crítica no NVD (CVSS 3.1: 9.8). O advisory do GitHub classifica como alta (CVSS 4.0: 8.7). A diferença vem da versão do CVSS e da avaliação de cada fonte; nas duas, é falha para corrigir.
- Versões afetadas: pelo advisory, até a 7.5.4 e a 8.0.0. Na prática, toda a linha 6.x abaixo de 6.11.6 também.
- Correções: 7.5.5 e 8.0.1, listadas no advisory, e 6.11.6, backport da mesma correção para a linha 6.x publicado pelos mantenedores em maio de 2026.
- Condição para explorar: o atacante precisa controlar ou influenciar o esquema carregado pelas APIs de reflexão. Aplicações que só decodificam mensagens com esquemas próprios e confiáveis não são afetadas diretamente.
Na Evolution API o protobufjs é usado pela pilha do WhatsApp com esquemas que vêm no próprio código, então o risco prático era baixo. Mesmo assim, corrigimos: uma crítica que fica "aceita" no relatório vira ruído, e ruído é o que faz uma equipe deixar de olhar o próximo alerta, que pode ser real.
A versão vulnerável estava escondida
A primeira reação é procurar o pacote na raiz do node_modules. Lá ele estava na 7.5.5, já corrigido. O problema estava num nível abaixo:
node_modules/protobufjs 7.5.5 (corrigido)
node_modules/libsignal/node_modules/protobufjs 6.8.8 (vulnerável)
O libsignal, usado na criptografia do WhatsApp, fixa a versão exata "protobufjs": "6.8.8" no seu package.json. Como a cópia da raiz não satisfaz essa exigência, o npm instala uma cópia própria dentro do pacote. Quem confere só a versão da raiz (npm ls protobufjs --depth=0, ou o package.json da aplicação) deixa essa cópia passar. O Trivy lê todos os package.json da imagem e por isso a encontra.
Para localizar todas as cópias de um pacote dentro de uma imagem:
docker run --rm --entrypoint sh SUA_IMAGEM -c \
'find / -path "*/node_modules/protobufjs/package.json" 2>/dev/null | xargs grep -H "\"version\""'
Por que não bastava atualizar
O caminho natural seria esperar uma versão nova da Evolution API ou do libsignal. Nenhum dos dois tinha release estável com a correção, e uma falha crítica não deveria esperar o calendário de terceiros. Também descartamos subir o protobufjs do libsignal para a 7.x: mudar de versão principal pode alterar APIs internas e quebrar justamente a criptografia das mensagens.
A boa notícia é que a linha 6.x ganhou a 6.11.6 com a correção. Dentro da mesma versão principal, a troca é segura desde que as dependências da versão nova já existam na imagem.
Passo a passo da correção
- Imagem derivada, não fork. Em vez de recompilar o projeto, criamos uma camada por cima da imagem original que só troca o que precisa. Aplicação, usuário, entrypoint e comando continuam os do fornecedor, o que facilita acompanhar as próximas versões.
- Conferir as dependências da versão nova. Antes de trocar, comparamos as
dependenciesda 6.11.6 (npm view [email protected] dependencies) com o que a imagem resolve a partir da pasta do pacote. Todas já estavam lá, inclusive olong4.x que olibsignaltraz aninhado. Se faltasse alguma, a troca não seria só "copiar a pasta". - Trocar no lugar. Baixamos o pacote oficial com
npm pack [email protected]e substituímos a pasta aninhada, mantendo o dono dos arquivos e anode_modulesinterna que existia. - Tirar o que não roda. O tarball da 6.11.6 traz a pasta
cli/(as ferramentaspbjsepbts) com dependências próprias, que o Trivy passou a apontar. Em produção ninguém usa essa CLI, então ela saiu da imagem: o que não está lá não precisa ser corrigido. - Aproveitar a viagem. Com o mesmo critério (mesma versão principal e nenhuma dependência nova), atualizamos outros pacotes da imagem e os pacotes do sistema operacional.
- Testar o que importa. Antes de publicar a imagem, subimos o container com um Postgres descartável e validamos: as migrations rodaram, a API respondeu, criamos uma instância de WhatsApp e o QR code foi gerado. O QR code é o teste que interessa aqui, porque só aparece se a conversa com os servidores do WhatsApp, que passa pelo
libsignale peloprotobufjs, funcionar. - Escanear de novo. Rodamos o Trivy na mesma versão usada pelo scan diário e confirmamos que a CVE-2026-41242 saiu do relatório.
- Trocar com plano de volta. A imagem anterior continua no registry; voltar é um comando. Depois da troca, conferimos que as instâncias reconectaram.
E se você monta a Evolution a partir do código?
Quem faz o build da Evolution API a partir do repositório tem um caminho mais simples: forçar a versão corrigida com overrides no package.json, o que vale também para dependências aninhadas.
{
"overrides": {
"libsignal": {
"protobufjs": "6.11.6"
}
}
}
Depois do npm install, confirme com npm ls protobufjs (que lista todas as cópias, inclusive as aninhadas) que nenhuma ficou abaixo da 6.11.6, e repita o teste do QR code antes de ir para produção. No pnpm o equivalente é a chave pnpm.overrides.
O que levamos deste caso
- Escaneie a imagem, não só o projeto. O que roda em produção é a imagem, com tudo o que ela carrega, inclusive dependências que você nunca declarou.
- Procure todas as cópias do pacote. A raiz do
node_modulescorrigida não garante nada. - Prefira a mesma versão principal. É o que permite corrigir sem regressão quando o fornecedor não ajuda.
- Remova o que não é usado. Menos código na imagem é menos falha para corrigir.
- Teste o fluxo que a dependência sustenta, não só se o container sobe.
Se você usa a Evolution API, veja também nosso guia sobre a CVE-2026-91997, que expõe o endpoint /metrics, outra falha recente do projeto, esta resolvida com configuração.
Perguntas frequentes
Minha Evolution API está vulnerável à CVE-2026-41242?
Se a imagem tem alguma cópia do protobufjs abaixo de 6.11.6 (ou da 7.x abaixo de 7.5.5), o scanner vai apontar a falha. A imagem oficial da 2.3.7 traz a 6.8.8 dentro do libsignal. O risco prático depende de um atacante conseguir influenciar os esquemas carregados, o que não é o uso normal da Evolution, mas a recomendação é corrigir.
Posso simplesmente subir o protobufjs do libsignal para a 7.x?
Não recomendamos. O libsignal fixa a 6.8.8, e mudar de versão principal pode quebrar a criptografia das mensagens. A 6.11.6 corrige a falha mantendo a mesma linha.
Atualizei para a 6.11.6 e o npm audit (ou o Dependabot) ainda acusa a falha. A correção não funcionou?
Provavelmente funcionou. Essas ferramentas leem o advisory do GitHub, que registra só as correções 7.5.5 e 8.0.1 e marca como afetado tudo até a 7.5.4. Como a 6.11.6 é um backport publicado depois, ela pode continuar sendo apontada como falso positivo. Para confirmar, verifique se a cópia instalada é mesmo a 6.11.6 (npm ls protobufjs) e confira a release da 6.11.6, que traz o backport da correção. Scanners com base própria de vulnerabilidades, como o Trivy que usamos, já reconhecem a versão como corrigida.
Preciso de uma ferramenta paga para achar dependências aninhadas?
Não. O Trivy é gratuito e de código aberto: trivy image --severity CRITICAL,HIGH SUA_IMAGEM lista as falhas com o caminho de cada pacote dentro da imagem.
Corrigir a imagem por conta própria não complica as próximas atualizações?
Complica menos do que manter um fork. Como a camada só troca pacotes por cima da imagem original, basta refazê-la sobre a versão nova quando ela sair, ou descartá-la se a versão nova já trouxer a correção.
Conclusão
A CVE-2026-41242 mostrou um ponto que vale para qualquer stack: a falha crítica nem sempre está onde você procura primeiro, e o fornecedor nem sempre vai corrigir no seu prazo. Com uma imagem derivada, troca dentro da mesma versão principal, remoção do que não é usado e um teste do fluxo real, dá para fechar a falha sem esperar o fornecedor e sem colocar a produção em risco. Para aprofundar em Docker, Node.js e segurança de aplicações, conheça os cursos da plataforma da Hcode.
Fontes
- GHSA-xq3m-2v4x-88gg: protobufjs has an arbitrary code execution issue, GitHub Advisory Database.
- CVE-2026-41242, NVD.
- protobufjs v6.11.6: backport da correção da CVE-2026-41242, GitHub.
- Releases da Evolution API, GitHub.
- Trivy, Aqua Security.
- overrides no package.json, documentação do npm.