Revogação de tokens clássicos não elimina risco de publicações comprometidas
O incidente conhecido como Sha1-Hulud funcionou como um divisor de águas para o ecossistema JavaScript. Após o ataque, em dezembro de 2025, o npm anunciou uma reformulação profunda em seu modelo de autenticação, prometendo reduzir a superfície de ataques à cadeia de suprimentos de software. O foco principal foi eliminar os chamados “tokens clássicos” – credenciais de longa duração e com amplo escopo de permissões, que, quando expostas, permitiam a publicação de versões maliciosas de pacotes sem qualquer validação pública prévia do código-fonte.
Com a mudança, o npm passou a priorizar tokens de sessão de curta duração, normalmente com validade de cerca de duas horas, obtidos via npm login. A autenticação multifator (MFA) passou a ser habilitada como padrão para a publicação de pacotes, aumentando a barreira contra invasores que tentassem acessar contas de mantenedores apenas com usuário e senha. Em paralelo, a plataforma começou a incentivar de forma mais agressiva o uso do modelo OIDC Trusted Publishing: em vez de guardar segredos estáticos em pipelines de CI, cada execução do sistema de integração contínua obtém credenciais temporárias, válidas somente pelo tempo necessário para aquele processo.
Apesar de representar um avanço importante, especialistas em segurança alertam que essas mudanças, por si só, não são suficientes para eliminar o risco de publicações comprometidas. A cadeia de suprimentos de software continua vulnerável a uma série de vetores de ataque, principalmente aqueles que exploram o elo humano do processo de autenticação e publicação.
Um dos pontos mais sensíveis é o phishing direcionado ao console do npm. No ataque que comprometeu o pacote ChalkJS, por exemplo, o mantenedor foi enganado por uma campanha de engenharia social que coletou tanto a senha quanto o código de autenticação multifator. Em um cenário como esse, mesmo com tokens de curta duração, o invasor dispõe de alguns minutos preciosos – mais do que o suficiente para publicar uma nova versão maliciosa do pacote, afetando possivelmente milhares de projetos que dependem dele.
Outro problema é a existência de exceções e brechas operacionais no próprio modelo de MFA. Em determinados cenários, ainda é possível gerar tokens com validade de até 90 dias, configurados com bypass de MFA para certas operações. Na prática, isso recria um ambiente parecido com o antigo modelo de tokens permanentes: credenciais duradouras, com alto poder de ação e menos barreiras de validação. Se um atacante obtém acesso à conta de um mantenedor que adotou esse tipo de token, ele pode publicar versões maliciosas em nome do autor legítimo – justamente o tipo de abuso que a atualização do npm pretendia mitigar.
Por isso, a discussão atual não se limita a “revogar tokens clássicos”, mas a redesenhar toda a estratégia de autenticação, autorização e publicação de pacotes. O objetivo é construir um ecossistema em que a publicação maliciosa não dependa apenas de “roubar um token”, mas exija romper múltiplas camadas de proteção, preferencialmente detectáveis e auditáveis.
Entre as recomendações mais debatidas para fortalecer a segurança do Node.js e do registro npm, destacam-se algumas medidas estruturantes. Uma das principais é tornar o OIDC Trusted Publishing o padrão obrigatório em médio e longo prazo, substituindo completamente a dependência de tokens estáticos. Isso desloca o foco da proteção de “segredos guardados em arquivos” para a gestão segura de identidades e permissões dinâmicas em serviços de nuvem e pipelines de CI/CD.
Outra sugestão recorrente é tornar o uso de MFA obrigatório também para uploads locais de pacotes, não apenas em fluxos específicos de publicação. Isso passa por eliminar, gradualmente, os tokens com bypass de MFA ou limitar seu uso a contextos extremamente restritos, com forte monitoramento e escopo mínimo. Quanto menos exceções existirem, menor será a chance de um atacante encontrar um caminho menos protegido para publicar código malicioso.
Especialistas também defendem o uso de metadados públicos nas releases que sinalizem as práticas de segurança adotadas pelos mantenedores. Informações como “publicado via OIDC”, “pipeline reprodutível”, “verificado por revisão de pares” ou “assinatura de pacote habilitada” podem não impedir um ataque diretamente, mas aumentam a transparência e permitem que empresas e desenvolvedores priorizem dependências com maturidade de segurança mais elevada.
Um consenso crescente é de que credenciais de curta duração, estreitamente vinculadas à identidade real do desenvolvedor ou ao contexto exato de execução do pipeline, são fundamentais para reduzir a superfície de ataque. Em vez de uma chave estática que “abre todas as portas por meses”, o ideal é que cada ação sensível dependa de credenciais renovadas, com escopo mínimo e contexto bem definido. Isso vale tanto para interações humanas (login no console) quanto para automações (publicações por CI/CD).
Além das mudanças no modelo de autenticação, uma abordagem complementar ganha força: reconstruir os pacotes a partir de código-fonte verificável, em vez de confiar cegamente nos artefatos já empacotados e publicados no npm. Em outras palavras, não assumir que o arquivo disponibilizado no registro é fiel ao repositório original, mas sim recompilar ou reempacotar a partir do upstream sempre que possível.
Análises de incidentes com pacotes comprometidos apontam que, em cerca de 98,5% dos casos de malware, o código malicioso estava presente apenas no artefato publicado, e não no repositório de origem. Isso significa que, se as organizações passassem a construir pacotes diretamente do código upstream verificado, a exposição a versões alteradas maliciosamente seria drasticamente reduzida. O atacante teria que comprometer o repositório público – o que é mais visível, auditável e muitas vezes sujeito a revisão da comunidade – em vez de apenas manipular o passo final de empacotamento.
Esse modelo se alinha ao chamado “modelo do queijo suíço” de segurança. A ideia é simples: cada camada de defesa tem falhas (os “buracos”), mas, ao colocar várias camadas sobrepostas, a probabilidade de todos os buracos se alinharem diminui significativamente. No contexto do npm, isso significa combinar autenticação forte, tokens curtos, OIDC, pipelines reprodutíveis, verificação de integridade e monitoramento contínuo, em vez de apostar em uma única solução milagrosa.
Para desenvolvedores e equipes de tecnologia, isso se traduz em uma série de boas práticas que vão além das configurações padrão da plataforma. Entre elas, vale destacar:
– Habilitar MFA em todas as contas de mantenedores, usando preferencialmente chaves de segurança físicas ou aplicativos autenticadores, evitando SMS sempre que possível.
– Evitar o uso de tokens de longa duração e revisar periodicamente quais tokens existem, quais permissões carregam e se ainda são necessários.
– Migrar gradualmente para modelos de publicação via OIDC em pipelines de CI/CD, removendo segredos estáticos armazenados em variáveis de ambiente ou arquivos de configuração.
– Implementar processos de revisão de código para mudanças em scripts de build, arquivos de empacotamento e etapas de pós-instalação – justamente onde malwares costumam ser injetados.
– Monitorar dependências por meio de scanners de vulnerabilidades e ferramentas específicas para detecção de comportamento malicioso em pacotes.
Organizações com cadeias de suprimentos mais complexas podem ir além e adotar repositórios internos espelhados do npm, onde apenas pacotes previamente analisados ou reconstruídos a partir da fonte são disponibilizados para uso interno. Esse tipo de “filtro corporativo” não elimina a necessidade de cuidado dos desenvolvedores, mas reduz a chance de que um pacote novo e malicioso, recém-publicado, seja automaticamente integrado em produção.
A educação dos times também é um pilar essencial. Ataques como o que atingiu o ChalkJS se aproveitam não apenas de falhas técnicas, mas de confiança excessiva em e-mails, mensagens diretas e supostos avisos urgentes de segurança. Treinamentos em phishing, simulações de ataques e criação de canais oficiais de comunicação interna para tratar alertas de segurança ajudam a diminuir a efetividade dessas campanhas de engenharia social.
Outro ponto importante é a adoção de mecanismos de assinatura de pacotes e verificação criptográfica de integridade. Embora ainda não sejam onipresentes no ecossistema npm, iniciativas de assinatura dão aos consumidores uma forma adicional de conferir se o pacote instalado foi realmente publicado pelo mantenedor esperado, sem alterações no caminho. Em ambientes críticos, combinar assinatura, hashes verificados e repositórios internos pode criar uma barreira substancial contra adulterações.
Para os próprios mantenedores de bibliotecas, a responsabilidade vai além de “escrever bom código”. Eles precisam tratar sua conta no npm como um ativo sensível, equivalente ao acesso ao repositório de código ou à infraestrutura de produção. Isso inclui uso de senhas fortes, gestão rigorosa de tokens, revisão frequente de permissões concedidas a colaboradores e automações e, principalmente, atenção a comunicações suspeitas que peçam credenciais ou códigos MFA.
Por fim, é importante reconhecer que não existe segurança absoluta na cadeia de suprimentos de software. A revogação dos tokens clássicos foi um passo na direção correta, mas ela resolve apenas uma parte do problema. O verdadeiro ganho vem da combinação de várias medidas: autenticação forte, automação segura, transparência nas práticas de publicação, reconstrução a partir da fonte, monitoramento de anomalias e educação contínua dos profissionais envolvidos.
Enquanto o ecossistema evolui em direção a padrões mais robustos, desenvolvedores, empresas e mantenedores precisam assumir um papel ativo. Depender apenas das configurações padrão do npm ou de qualquer outro registro é insuficiente. A proteção contra publicações comprometidas exige cultura de segurança, processos bem definidos e uma postura permanente de desconfiança saudável em relação a tudo o que entra na sua cadeia de dependências.