Aikido

A armadilha do upgrade: quando o upgrade é a resposta errada para uma CVE

Escrito por
Sooraj Shah

O conselho é sempre o mesmo quando uma ferramenta de vulnerabilidade sinaliza uma CVE: faça upgrade. Mova para a versão corrigida para que você possa fechar o ticket e seguir em frente. Tornou-se um reflexo tão automático que ninguém para para perguntar se realmente funcionará.

A correção proposta falha de três maneiras específicas. Não há versão para fazer upgrade e nunca haverá, a versão corrigida ainda não foi lançada, ou a correção é lançada e quebra seu aplicativo. 

Em resumo, as melhores práticas e todos os frameworks, de SOC2 a ISO27001, dizem para manter suas dependências atualizadas. Mas fazer upgrade não equivale a corrigir, e, no entanto, é a única resposta que muitas ferramentas oferecem. 

Nem sempre foi um instinto errado. Os mantenedores (felizmente) têm corrigido vulnerabilidades na versão mais recente, e por anos isso foi suficiente.

CVEs são reportadas > mantenedores as corrigem > você faz upgrade > você obtém a correção.

Mas os mantenedores geralmente não voltam para corrigir versões mais antigas. Assim, as equipes foram condicionadas a sempre fazer upgrade para a versão mais recente quando podiam, e os atacantes notaram esse padrão e aprenderam a explorá-lo. Agora, você faz upgrade para ter a CVE corrigida, há alguma chance de que em algum lugar na atualização haja malware, então baixar a versão mais recente não é mais automaticamente seguro.  

No início deste ano, atacantes comprometeram uma conta de mantenedor responsável por alguns dos pacotes mais baixados no npm. chalk e debug, somando mais de dois bilhões de downloads por semana. Eles publicaram versões maliciosas através do canal oficial, e todo pipeline configurado para auto-atualização os puxou diretamente. Equipes seguindo as melhores práticas estavam distribuindo malware em minutos. 

É uma situação sem saída. Você se mantém atualizado e corre o risco de baixar malware, ou você congela e acumula dívida de segurança. Isso é o que chamamos de armadilha do upgrade. A versão que você executa e as correções de segurança aplicadas a ela não precisam ser a mesma decisão.

As três maneiras pelas quais o upgrade falha

É claro que o “upgrade” funciona muitas vezes e ainda é importante. Mas há três situações em que ele falha. 

A primeira é quando não há uma versão corrigida para a qual migrar (e nunca haverá). Considere request, um dos clientes HTTP mais usados no Node, que foi descontinuado desde 2020. E, no entanto, ele ainda aparece em todos os lugares, geralmente arrastado por algum pacote pai que ninguém mexeu há anos. Quando você executa uma ferramenta SCA sobre o request, a ferramenta encontra uma CVE para bypass de mitigação de server-side request forgery (SSRF). Adivinhe qual é a correção aqui, de acordo com a ferramenta SCA? Sim, fazer upgrade.

Mas o problema é que não há nada para fazer upgrade, e nunca haverá. request não é mantido há anos. O aviso praticamente diz isso, observando que a falha afeta apenas as versões que o mantenedor não oferece mais suporte (ou seja, todas as versões). Então, neste caso, “upgrade” na verdade significa remover request e migrar para algo como axios ou node-fetch. Isso é uma reescrita e uma migração, e significa que, até que alguém tenha tempo para isso, a CVE simplesmente fica lá. 

Isso pressupõe que a correção deve vir do mantenedor. Para pacotes EOL, alguém ainda precisa entender a vulnerabilidade e escrever uma correção para a versão já em uso. As distros fazem isso para pacotes de nível de SO há anos. A mesma abordagem agora existe para bibliotecas de aplicativos, que é onde a maioria das equipes está presa.

O segundo tipo de upgrade é quando a correção não existe ainda mesmo que o pacote esteja ativo. A biblioteca popular lodash passou um período de tempo no ano passado com duas vulnerabilidades divulgadas afetando todas as versões publicadas até e incluindo 4.17.23. Como essa era a versão mais recente, não havia nada para fazer upgrade. npm audit sinalizou as CVEs e relatou que não havia correção disponível. Assim, embora o conselho de fazer upgrade fosse válido, não era realmente viável porque a versão corrigida não havia sido lançada.

O terceiro é quando a correção é lançada e quebra sua aplicação. CVE-2026-48937 no Node é um exemplo recente. A correção para a vulnerabilidade veio junto com uma SEMVER-MAJOR atualização para a nghttp2 dependência e a remoção do suporte a sinalização de prioridade HTTP/2. O comportamento vulnerável e o recurso sendo removido faziam parte do mesmo código subjacente, então não havia como aplicar a correção de segurança sem também aplicar a mudança disruptiva. Os usuários tiveram que procurar por setPriority e .priority() e removê-los antes que pudessem fazer qualquer upgrade. 

Este é o risco de qualquer upgrade. Um novo lançamento pode mudar o comportamento de um pacote o suficiente para quebrar algo que estava funcionando, forçar outras dependências a fazerem upgrade junto, ou chegar como uma versão principal que exige uma migração antes mesmo de ser instalada. 

E indo um passo além, se você atualiza um pacote, pode ter que atualizar outros cinco. Um deles pode quebrar algo que seu sistema depende. A engenharia então tem a escolha entre um item do roadmap que gera receita e o upgrade. Adivinhe qual vence 😬. Você acaba com dívida técnica e um acúmulo de CVEs. 

Como a IA mudou o cenário

A maioria das empresas tem um backlog de CVEs grande demais para ser resolvido, e estão apreensivas porque os modelos de fronteira mais recentes podem encontrar vulnerabilidades mais rapidamente. Mas o que é mais ameaçador é que eles podem encadear CVEs de média gravidade de uma forma que os transforma em um padrão de exploração crítico. O modelo atual de varredura, triagem e tentativa de distribuir esse trabalho para os engenheiros não escala rápido o suficiente para gerenciar esse problema. A IA está efetivamente agravando um problema existente e tornando mais urgente para as organizações corrigi-lo.

O que a indústria faz a respeito

A atualização era a única resposta realista por muito tempo. Os backlogs de CVE e as builds quebradas que se seguiram foram uma consequência previsível do conjunto limitado de escolhas. Existem, em geral, três abordagens para este problema. Duas delas trocam um problema por outro. A terceira se aproxima mais de realmente fechar o CVE sem criar um novo.

A primeira é a triagem no ponto de consumo. Antes que um pacote chegue à sua build, ele é verificado: esta dependência é segura para instalar? É uma camada necessária, especialmente após ataques como chalk e debug. Mas não se aplica a pacotes vulneráveis já em produção. É um portão de entrada em vez de uma correção e, fora desse escopo, a resposta continua sendo a atualização.  

A segunda opção consiste em transferir as equipas para uma pilha de substituição reforçada. Em vez de corrigir o que as equipas já utilizam, estas são empurradas para um ecossistema proprietário que não controlam. Isto pode funcionar para aplicações totalmente novas, mas, no caso de sistemas de produção ligados a bibliotecas e imagens base específicas, transforma a correção num projeto de migração. Uma vez lá dentro, sair torna-se um projeto à parte.

A terceira opção consiste em aplicar a correção à versão já em uso. A maioria das organizações não tem capacidade, conhecimentos especializados nem vontade para o fazer. Quando um CVE é corrigido a montante, a parte mais reduzida do código que o corrige é isolada da versão mais recente e aplicada de forma limpa à versão mais antiga que já está a utilizar. Verificar se nada mais mudou requer verdadeira especialização e manutenção contínua. As distribuições têm vindo a fazer versões disto há anos. Fazer o mesmo em bibliotecas de aplicações, automaticamente, ao ritmo a que os CVEs surgem, é um problema completamente diferente. No caso de pacotes em fim de vida (EOL), para os quais não está prevista qualquer correção a montante, alguém tem ainda de compreender a vulnerabilidade e escrever uma correção para a versão já em uso. Esse mesmo trabalho existe agora como uma opção escalável para bibliotecas de aplicações, que é onde a maioria das equipas se encontra bloqueada. O único caso em que isto não se aplica é quando ainda não existe qualquer correção a montante. Se o mantenedor não tiver escrito o patch, não há nada para isolar e aplicar. O CVE permanece por aí até que alguém o faça.

Você mantém a versão em que seu aplicativo já confia, aplica apenas a correção, e não acumula CVEs contra uma versão congelada nem puxa a versão mais recente e tudo o que vem com ela.

Pense na sua stack de software como uma casa em que você mora há anos. A maioria das ferramentas ou monitora o que entra, ou entrega uma lista de reparos e diz para você resolver, ou pede para você se mudar para uma casa nova e menor que elas construíram. Consertar a casa em que você já mora é o que a maioria das equipes realmente quer.

Agora existe uma opção que faz exatamente isso: corrigir vulnerabilidades nos pacotes de código aberto dos quais sua aplicação depende, sem a necessidade de upgrade, com Aikido Libraries.

Compartilhar:

https://www.aikido.dev/blog/cve-upgrade-breaking-changes-open-source

Assine para receber notícias

4.7/5
Cansado de falsos positivos?

Experimente Aikido como 100 mil outros.
Começar Agora
Obtenha um tour personalizado

Confiado por mais de 100 mil equipes

Agende Agora
Escaneie seu aplicativo em busca de IDORs e caminhos de ataque reais

Confiado por mais de 100 mil equipes

Iniciar Escaneamento
Veja como o pentest de IA testa seu aplicativo

Confiado por mais de 100 mil equipes

Iniciar Testes

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.