- O pacote Bitwarden CLI para npm foi comprometido como parte do ataque de cadeia de suprimentos da Checkmarx em andamento, e o impacto confirmado até agora se limita ao build
@bitwarden/cli2026.4.0 - O malware
bw1.jsincluído no pacote usa a mesma infraestrutura e o mesmo método de ofuscação, comoaudit.checkmarx[.]cx/v1/telemetry, e também se alinha a indícios de comprometimento de CI/CD por meio de uma GitHub Action comprometida - O escopo de coleta vai muito além de tokens do GitHub, alcançando credenciais da AWS, Azure e GCP,
.npmrc, chaves SSH, variáveis de ambiente e até arquivos de configuração do Claude/MCP - As informações roubadas são usadas para criar e commitar em repositórios públicos no GitHub, espalhar o ataque por republicação com tokens npm e injeção de workflows, além de incluir mecanismos de persistência como modificação de
~/.bashrce~/.zshrc - Organizações que usam o Bitwarden CLI devem tratar este incidente como exposição de credenciais e comprometimento de CI/CD, com foco na revisão de logs de CI e na rotação de segredos potencialmente expostos
Visão geral
- O pacote npm do Bitwarden CLI foi comprometido como parte do ataque de cadeia de suprimentos da Checkmarx em andamento, e a versão afetada confirmada é
@bitwarden/cli2026.4.0- O código malicioso estava presente em
bw1.js, incluído no pacote - O vetor de ataque é consistente com indícios de uso de uma GitHub Action comprometida dentro do pipeline de CI/CD da Bitwarden, seguindo o mesmo padrão de campanha observado em outros repositórios
- O código malicioso estava presente em
- Até o momento, o escopo confirmado está limitado ao build do Bitwarden CLI, e o comprometimento segue o vetor de supply chain via GitHub Actions identificado na campanha mais ampla da Checkmarx campaign
- Apenas o pacote CLI para npm está relacionado ao incidente
- Até agora não foi confirmado impacto na extensão do Chrome, no servidor MCP ou em outros artefatos oficiais
- A investigação continua em andamento, e uma análise técnica completa, as versões afetadas, os indicadores de comprometimento e as orientações de resposta serão divulgados posteriormente
- Se você usa o Bitwarden CLI, é necessário revisar os logs de CI e rotacionar os segredos que possam ter sido expostos
Análise técnica
- O payload malicioso
bw1.jscompartilha a infraestrutura central com omcpAddon.jsda Checkmarx analisado no dia anterior- Usa o mesmo endpoint de C2,
audit.checkmarx[.]cx/v1/telemetry, e está ofuscado com__decodeScramblede a seed0x3039 - Também realiza exfiltração baseada em commits via API do GitHub e roubo de tokens com republicação via registro npm
- Usa o mesmo endpoint de C2,
- A estrutura do payload embutido também pertence à mesma família
- Dentro de uma estrutura gzip+base64 há um script Python que varre a memória do
Runner.Workerdo GitHub Actions em busca de tokens do GitHub - Também inclui um loader
setup.mjspara pacotes npm republicados, um workflow YAML do GitHub Actions, uma chave pública RSA hardcoded e uma string de manifesto ideológico
- Dentro de uma estrutura gzip+base64 há um script Python que varre a memória do
- O escopo de coleta de credenciais é muito amplo
- Tokens do GitHub são coletados por scraping da memória do
Runner.Workere de variáveis de ambiente - Credenciais da AWS são procuradas em arquivos sob
~/.aws/e em variáveis de ambiente - Tokens do Azure são coletados por meio do
azd, e credenciais da GCP porgcloud config config-helper .npmrc, chaves SSH, variáveis de ambiente e arquivos de configuração do Claude/MCP também estão entre os alvos
- Tokens do GitHub são coletados por scraping da memória do
- O método de exfiltração via GitHub também foi confirmado em detalhes
- O malware cria repositórios públicos sob a conta da vítima seguindo a convenção de nomes com tema de Dune
{word}-{word}-{3digits} - Em seguida, commita resultados criptografados e insere tokens na mensagem de commit junto com o marcador
LongLiveTheResistanceAgainstMachines
- O malware cria repositórios públicos sob a conta da vítima seguindo a convenção de nomes com tema de Dune
- O mecanismo de propagação pela cadeia de suprimentos também está presente
- Com tokens npm roubados, ele procura pacotes com permissão de escrita e os republica com um preinstall hook injetado
- Também injeta workflows do GitHub Actions para coletar mais segredos dos repositórios
- Existe um kill switch para locale russo
- Se o locale do sistema começar com
"ru", o malware encerra silenciosamente - Ele verifica
Intl.DateTimeFormat().resolvedOptions().localee as variáveis de ambienteLC_ALL,LC_MESSAGES,LANGUAGEeLANG
- Se o locale do sistema começar com
- O runtime é Bun v1.3.13, baixado do GitHub Releases
Diferenças em relação ao incidente da Checkmarx
- O
bw1.jscontém indicadores adicionais de comprometimento que não apareciam na documentação do incidente da Checkmarx- Usa o arquivo de lock hardcoded
/tmp/tmp.987654321.lockpara impedir execução simultânea - Injeta o payload em
~/.bashrce~/.zshrcpara garantir persistência em perfis de shell - Usa branding explícito, definindo a descrição do repositório como
Shai-Hulud: The Third Cominge incluindo a string de debug"Would be executing butlerian jihad!"
- Usa o arquivo de lock hardcoded
- Embora as ferramentas compartilhadas sugiram fortemente conexão com o mesmo ecossistema de malware, as assinaturas operacionais tornam a atribuição mais difícil
- Após a descoberta do ataque à Checkmarx, a TeamPCP alegou autoria por meio da conta social
@pcpcats - Esse malware tentou se disfarçar com descrições aparentemente legítimas
- Após a descoberta do ataque à Checkmarx, a TeamPCP alegou autoria por meio da conta social
- Este payload adota uma postura pública diferente
- Marcas ideológicas como nomes de repositórios Shai-Hulud, o manifesto
"Butlerian Jihad"e mensagens de commit defendendo resistência contra máquinas aparecem diretamente dentro do malware - Permanecem em aberto várias possibilidades: outro operador usando a mesma infraestrutura, uma facção mais ideológica ou uma mudança na postura pública da campanha
- Marcas ideológicas como nomes de repositórios Shai-Hulud, o manifesto
Recomendações
- Organizações que instalaram o pacote npm malicioso do Bitwarden devem tratar este incidente como um caso de exposição de credenciais e comprometimento de CI/CD
- Remova imediatamente o pacote afetado de sistemas de desenvolvimento e ambientes de build, e substitua todas as credenciais que possam ter sido expostas nesses ambientes
- Isso inclui tokens do GitHub, tokens npm, credenciais de nuvem, chaves SSH e segredos de CI/CD
- No GitHub, é preciso verificar criação não autorizada de repositórios e workflows anormais
- Verifique arquivos inesperados em
.github/workflows/, execuções suspeitas de workflow, downloads de artifacts e repositórios públicos que sigam o padrão de nome com tema de Dune{word}-{word}-{3digits} - Se houver possibilidade de impacto, verifique os repositórios recém-publicados em busca das palavras-chave abaixo
atreidescogitorfedaykinfremenfutargesseritgholaharkonnenheighlinerkanlykralizeclasgunlazamelangementatnavigatorornithopterphibianpowindahpranaprescientsandwormsardaukarsayyadinasietchsiridarsligstillsuitthumpertleilaxu
- Verifique arquivos inesperados em
- No npm, deve-se auditar se houve publicações não autorizadas
- Verifique publishes não aprovados, mudanças de versão e hooks de instalação recém-adicionados
- Em ambientes de nuvem, os logs de acesso devem ser reavaliados
- É necessário rastrear acessos anormais a segredos, uso de tokens e credenciais recém-emitidas
- Em endpoints e runners, é preciso rastrear a infraestrutura de exfiltração observada e os vestígios de acesso a arquivos
- Procure conexões externas para
audit[.]checkmarx[.]cx - Verifique se houve execução de Bun em ambientes onde isso não costuma ocorrer
- Examine vestígios de acesso a
.npmrc,.git-credentials,.env, armazenamentos de credenciais em nuvem,gcloud,azeazd - Também verifique a presença de
/tmp/tmp.987654321.locke modificações em~/.bashrce~/.zshrc
- Procure conexões externas para
- No GitHub Actions, revise se houve criação de workflows não autorizados
- É preciso confirmar se workflows foram criados em branches temporárias
- Também deve ser verificado se artifacts como
format-results.txtforam gerados ou baixados
- No longo prazo, é necessário reduzir o raio de impacto de futuros incidentes de supply chain
- Reduza o escopo de permissões dos tokens e, quando possível, use credenciais de curta duração
- Restrinja permissões de criação e publicação de pacotes e fortaleça as permissões do GitHub Actions
- Desative acesso desnecessário a artifacts e monitore repositórios públicos ou mudanças em workflows criados fora do processo normal de release
Indicadores de comprometimento
-
Pacote malicioso
-
Indicadores de rede
94[.]154[.]172[.]43https://audit.checkmarx[.]cx/v1/telemetry
-
Indicadores no sistema de arquivos
/tmp/tmp.987654321.lock/tmp/_tmp_<Unix Epoch Timestamp>/package-updated.tgz
1 comentários
Comentários do Hacker News
Fico me perguntando se existe uma defesa melhor do que impor um tempo mínimo de espera antes do release
Se tivessem colocado só
min-release-age=7no.npmrc, parece que as 334 pessoas que baixaram o@bitwarden/cli 2026.4.0, publicado há cerca de 19 horas antes de ser identificado como malicioso, teriam escapadoIsso também parece se aplicar razoavelmente bem aos casos de
axios,ua-parser-jsenode-ipc; não impediria algo comoevent-stream, que ficou dormente por muito tempo, mas ainda assim parece eficaz contra a maioria dos ataques agudos de cadeia de suprimentosHá exemplos de configuração de como adicionar esse tempo de espera em npm/pnpm/bun/uv, e como não havia uma ferramenta de um clique para verificar e aplicar isso, acabei criando https://depsguard.com
Também acabei de ver https://cooldowns.dev, que segue uma ideia parecida
Ele não só impõe um tempo mínimo de espera para releases, como também funciona como um wrapper em torno de npm/uv etc., verificando cada dependência antes da instalação contra um banco de dados comercial de vulnerabilidades para checar problemas conhecidos ou sinais suspeitos
Na prática sempre vai ter alguém atualizando na hora, mas parece que o próprio processo de descobrir esse tipo de incidente depende bastante desses usuários que atualizam rápido
Se for inevitável puxar binários diretamente do registro, o cooldown pode reduzir um pouco o risco
Para os casos mais raros em que o comprometimento chega até o GitHub, parece necessário combinar heurísticas de commits e mantenedores com análise de mudanças de código baseada em IA, e revisão humana quando houver sinais estranhos
Trabalho nisso, aliás
O ponto central deste incidente é que o pipeline de build foi comprometido, e foi assim que os pacotes contaminados foram publicados
Ainda assim, se você coloca algo importante para o trabalho no npm, acho melhor fixar as dependências
Muita gente acha que o lockfile basta, mas se ainda houver um intervalo
^, ao atualizar o lockfile você pode acabar trazendo uma nova versão que não escolheu explicitamenteSe for um sistema capaz de afetar a sobrevivência da empresa, esse nível de incômodo vale a pena
https://github.com/doy/rbw é uma alternativa em Rust ao Bitwarden CLI
O ecossistema Rust também dá cada vez mais a impressão de estar caminhando para árvores de dependência grandes e profundas como no npm, mas ainda assim o número de autores em quem é preciso confiar é bem menor do que no caso típico em JavaScript
Pelo menos as versões estão fixadas
rbw + vaultwardenfunciona bem como uma versão em Rust e auto-hospedável do BitwardenOu talvez a tendência seja colocar mais funcionalidades na biblioteca padrão da linguagem
A experiência com o Bitwarden CLI foi péssima
Executei
bw listachando que veria só os nomes das senhas, mas na prática ele mostrou as senhas e até os códigos TOTP atuaisO mais assustador foi que, ao entrar por ssh num servidor e abrir o weechat dentro de uma sessão tmux, o conteúdo inteiro do comando
bwestava acessível no histórico de entrada do weechatNão faço ideia do porquê, e aquilo continuou lá mesmo atravessando sessões de tmux e weechat; só sumiu depois que reiniciei o servidor
Depois disso removi o CLI
bwimediatamente e não pretendo instalar de novoUso ghostty como terminal, aliás
Fico me perguntando se existe alguma extensão
bwclipara o weechat; eu nem sabia que o Bitwarden tinha CLI até agoraEu uso keepass localmente
Nunca usei o CLI, mas uso o plugin do navegador
Se isso for comprometido, é um desastre enorme, e não sei o que fazer para evitar
Fico pensando se a resposta seria continuar usando uma versão antiga já verificada
É estranho parar para pensar que uma parte considerável da minha vida depende de esses segredos continuarem secretos
Por isso não uso extensão de navegador para gerenciador de senhas
Depois de ver produtos com problemas de segurança na integração com navegador, passei a evitar completamente; confio relativamente mais na integração do iOS, mas ainda assim com cautela
Isso inclui gerenciadores de pacotes de desenvolvimento, gerenciadores de pacotes do sistema operacional, extensões de navegador e até atualizações automáticas de aplicativos independentes
Empresas como a Socket precisam de tempo para detectar updates maliciosos; se todo mundo baixar tudo minutos após a publicação, esse tipo de detecção perde o sentido
Recomendo muito essa configuração
O título me assustou um pouco, mas sinto que já faço tudo o que é razoável fazer sem cair em paranoia
https://cooldowns.dev
https://depsguard.com
Eu mantenho o segundo; se conhecesse o primeiro antes, talvez nem tivesse criado o meu
Os dois fazem quase a mesma coisa, e o meu acaba sendo um pouco exagerado por usar Rust
O mais importante aqui é que bastou um npm install
Se o ponto de comprometimento é o
preinstall, a ideia comum de inspecionar depois da instalação cai por terra na horaNesse ponto o payload já teve chance de executar
Isso fica ainda mais interessante em ambientes de agentes, CI e sandboxes efêmeros, porque mesmo com pouco tempo de exposição, se a instalação acontece repetidamente de forma automática, já é o suficiente para ser comprometido
Outro ponto importante é que esse payload não mirava apenas segredos: ele também tinha como alvo configurações de ferramentas de IA
Alterar perfis de shell pode se tornar um caminho para contaminar o contexto que o próximo assistente de programação vai ler
Escrevi mais longamente sobre essa perspectiva, junto com o trabalho do AgentSH, em https://www.canyonroad.ai/blog/the-install-was-the-attack/
No fim das contas você vai executar o binário real de qualquer forma
E, se for levar ao pé da letra, também seria possível baixar e inspecionar o pacote antes da instalação; se você não entende profundamente as garantias de comportamento e o escopo do instalador, parece ainda mais estranho confiar de forma meio improvisada no processo de baixar e descompactar código malicioso
Um kill switch por locale russo parece ao mesmo tempo ousado e covarde
Discretion is the better part of valorEm resumo, parece a postura de não atirar no próprio pé
No vazamento do
Vault7havia menções de que NSA e CIA deixavam rastros assim de propósito para confundir a origem, e é uma técnica que outros atores estatais certamente também poderiam usarParece um rastro de despiste óbvio demais, mas ao mesmo tempo reforça bastante a impressão de envolvimento de um ator estatal
A vida de quem usa KeePass tem muito menos desse tipo de estresse
Só nos últimos 5 anos, usar KeePass em infraestrutura local me poupou de vários incidentes de segurança
Não vejo por que algo assim seria impossível com uma ferramenta de acesso ao KeePass; então não entendo bem qual seria a diferença
Sempre achei que não dava, mas para ser sincero nunca investiguei a fundo
O que acontece se dois dispositivos adicionarem senhas diferentes enquanto estão offline e depois voltarem a ficar online?
Se você criptografa o backup, onde guarda essa senha? E onde guarda a senha do provedor de nuvem?
O que mais impressiona neste ataque é que os invasores precisaram acertar exatamente o momento em que o GitHub não estava fora do ar
https://mrshu.github.io/github-statuses/
Por isso eu simplesmente não uso gerenciador de senhas de terceiros
Porque você precisa continuar confiando que eles vão cuidar direito de segurança, updates e backups
Criei meu próprio gerador stateless de senhas, e com isso não preciso de backup nem sincronização de dados entre dispositivos
A ideia é usar uma senha mestra muito longa e forte, junto com o nome do serviço e o nome de usuário, e rodar um hash scrypt com parâmetros adequados para tornar brute force praticamente inviável
Também uso 2FA nas contas importantes