Uma ponte permanece em serviço durante cinquenta anos com um plano de inspeção fixo, sujeita a testes de carga e mantida ao longo de todo esse período. Um motor a jato utiliza o mesmo design durante décadas sob supervisão regulatória contínua. Na maioria das disciplinas de engenharia, um design estável e comprovado, combinado com manutenção ativa, é o objetivo principal. Designs mais recentes são tratados com muito mais rigor, uma vez que nunca foram verdadeiramente testados.
Mas, por alguma razão, na engenharia de software acontece o oposto. A versão mais recente é tratada como a mais segura. E esse instinto já teve consequências graves no passado. Uma backdoor permaneceu oculta em duas versões específicas de xz-utils, versões 5.6.0 e 5.6.1, inserida por um infiltrado que passou dois a três anos a planear a obtenção de autoridade para lançar versões. Qualquer pessoa que ainda estivesse a executar a linha antiga 5.4.x nunca esteve exposta, mas quem descarregou a versão mais recente — algo que as equipas de segurança costumam ser instruídas a fazer — acabou por executar um caminho de SSH com backdoor. A própria recomendação da CISA posteriormente foi fazer o downgrade, e não o upgrade.
Já defendemos anteriormente, naquilo a que chamamos 'a armadilha da atualização', que aplicar patches no preciso momento em que surge um CVE é uma falsa economia; está a escolher entre congelar o sistema e aceitar todas as alterações que acompanham a correção. xz-utils mostra-nos o lado oposto da mesma moeda. Manter-se onde estava era a escolha segura, e a versão mais recente representava a armadilha.
Uma forma de testar isto é perguntar a uma equipa de segurança quantos CVEs abertos possui; eles conseguirão responder rapidamente. No entanto, se perguntar porque é que um determinado pacote ou container image está a executar a versão atual, o mais provável é obter um "não sei". Simplesmente está, certo? Normalmente, baseia-se no que estava disponível quando o projeto começou, e atualizar parecia dar mais trabalho do que aquilo que valia. Indo um pouco mais além, se pedir um registo por escrito dessa decisão, é provável que receba uma resposta mais severa do género "porque haveríamos de fazer isso?".

Então, onde é que isto falha?
Muitas vezes, os engenheiros são levados a acreditar que um container image ou pacote se torna mais arriscado à medida que o número da versão envelhece. Mas o xz-utils exemplo prova que isto não é verdade; a versão mais antiga era segura porque nada de malicioso tinha chegado até ela, e as equipas que a utilizavam não se apressaram a adotar a versão mais recente assim que foi lançada. Naturalmente, existe a hipótese de muitas equipas simplesmente não terem tido tempo para atualizar, embora quisessem fazê-lo. Ainda assim, isso é preferível a não saber que versão está a executar, nem o motivo, que é a verdadeira falha aqui.
Em vez disso, as equipas devem ponderar que, se possuem uma versão de uma biblioteca que foi testada, compreendida e é de confiança, existe um valor real em mantê-la estável. A monitorização começa no momento em que um programador, agente ou pipeline de compilação solicita um container base image ou um pacote open-source, avaliando-o antes de este entrar no ambiente. É a primeira decisão numa cadeia de decisões que são tomadas.
Uma atualização é também uma decisão
A determinada altura, surgirá uma nova versão, mas aplicar um patch a um CVE significa aceitar tudo o resto que foi incluído nessa mesma versão. Isso inclui dependências transitivas, alterações nos valores predefinidos e caminhos de código que ninguém na equipa chegou a ler. Na maioria das vezes, esse risco é invisível e nada corre mal. Contudo — e é um grande 'contudo' —, as coisas podem correr mal. lodash passou parte de 2026 com uma vulnerabilidade divulgada de injeção de código arbitrário que afetava todas as versões publicadas. Quando a correção foi finalmente lançada como a versão 4.18.0, falhou de imediato porque o patch substituiu uma função interna diferente que nunca tinha sido importada, fazendo com que projetos reais começassem a falhar no espaço de um dia.
A versão foi imediatamente descontinuada, com uma nota a reencaminhar os utilizadores para lodash 4.17.21 em vez disso. A alteração disruptiva não tinha qualquer relação com a vulnerabilidade em si; tratou-se de um erro de empacotamento que veio incluído juntamente com a correção de segurança. A correção real só chegou na versão 4.18.1.
Nenhuma das opções em cima da mesa era verdadeiramente segura. Atualizar para a versão 4.18.0 interrompeu as compilações de imediato. Permanecer na 4.17.21 manteve a vulnerabilidade em aberto, enquanto todas as versões anteriores à 4.18.0 continuaram vulneráveis a explorações. Algumas equipas fizeram o downgrade de volta para a 4.17.x especificamente para escapar à compilação corrompida, trocando uma compilação funcional por um caminho de injeção de código ativo, sem necessariamente perceberem que essa foi a troca que fizeram.
Neste caso, as equipas que se encontravam numa posição mais forte foram aquelas que souberam se a sua própria aplicação sequer chamava o _ afetado.template caminho com input não fiável, e poderia avaliar essa exposição real em comparação com a alternativa avariada, em vez de avançar por defeito sem saber qual foi o verdadeiro custo.
Corrigir a vulnerabilidade sem substituir tudo o que está à volta
O backporting altera a equação. Pega na correção específica para a vulnerabilidade específica e aplica-a à versão que já está a executar, em vez de puxar tudo o resto que foi lançado em simultâneo a montante. Aplique-o a uma imagem de container e o CVE fica resolvido sem forçar uma nova imagem base. Aplique-o a um pacote e a mesma correção é feita sem um salto forçado para a versão mais recente, exatamente o salto que avariou projetos reais em execução lodash 4.18.0. Consegue resolver o problema de segurança sem alterar tudo o que está à volta.
Um SBOM deve justificar a sua existência, não apenas existir
Um SBOM, tal como tantos documentos relacionados com conformidade, é frequentemente preenchido uma vez e arquivado. Isso indica o que estava no sistema no dia em que alguém gerou o relatório. Mas o SBOM pode fazer muito mais pela sua postura de segurança do que isso. Pode servir de linha de base de software de confiança e ajudá-lo a gerir essa linha de base de forma contínua. Para isso, teria de garantir que se mantém atualizado e que é verificado face a novas divulgações à medida que vão surgindo. Para mim, este é o sinal mais evidente de que uma organização continua a monitorizar o software que executa, em vez de se limitar a navegar à vista com o que já lá está.
Queremos que o SBOM deixe de ser apenas um inventário ou um artefacto de conformidade. Deve ser uma superfície regulada e ativamente mantida.
Então, o que precisa de mudar?
Todas estas são decisões que precisam de ser tomadas. Algumas dizem respeito a um componente de software específico num determinado momento, como avaliar um pedido, fixar a sua versão e recorrer ao backporting em vez de forçar uma atualização. Outras, como manter ou não um SBOM atualizado, estão relacionadas com os processos que tem implementados. No fundo, cada uma delas é uma decisão sobre em quê confiar.
O mais fácil é deixar as coisas como estão, porque "funciona". Mas "funciona" não é verdade, pois não? O facto de algo funcionar não significa que vá funcionar sempre, nem que seja a forma mais segura de fazer as coisas, ou que seja a melhor forma de operar.
Na nossa perspectiva, a abordagem mais proativa e consciente da segurança seria controlar a alteração no ponto de entrada — avaliar os pacotes antes de um programador, agente ou sistema de compilação os consumir. A partir daí, deve ter a liberdade para decidir proativamente o que entra, fixar aquilo em que confia, mantê-lo e só alterá-lo quando houver uma razão para isso.
Permanecer numa versão não deve significar continuar exposto. Aikido Libraries aplica o backport da correção à versão que já está a executar, sem atualizações forçadas, sem migrações forçadas. Comece a aplicar patches aqui.