TL; DR
Între 1 aprilie și 3 mai 2026, un singur editor npm, user0001, înregistrat cu adresa Gmail neverificată tanvisoul9@gmail.com, a promovat discret șase pachete cu nume deliberat banale, care sună a infrastructură: centralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtime și node-env-resolve.
Cele mai recente două versiuni ale node-env-resolve, 1.0.7 și 1.0.8, au fost semnalate de sistemul de avertizare timpurie împotriva programelor malware (MEW) al Xygeni pe 2 mai și confirmate ca fiind malițioase pe 3 mai.
Implantul este neobișnuit pentru ceea ce nu este: nu există roboți Telegram, nu există apeluri OAST inverse, nu confuzieși nicio încercare de a obține acreditările AWS în momentul instalării. În schimb, postinstall.js plantează o intrare de persistență la bootare Windows, folosind o cheie Run HKCU care lansează wscript.exe împotriva unui stub VBS. Apoi generează un agent Node.js detașat care include module pentru captura de microfon, furtul istoricului browserului, realizarea de capturi de ecran și simularea mouse-ului/tastaturii.
Numim acest cluster DevTap, după kit, acesta pleacă să ruleze pe mașina unui dezvoltator.
Toate cele șase pachete erau disponibile pe npm la momentul scrierii. Le-am trimis către canalul de abuz al registrului. Apărătorii ar trebui să retragă orice instalări de la editor în așteptarea eliminării.
Clusterul: Șase pachete, un editor
Contul editorului user0001 este neverificat. Nu are SCM verificare, fără e-mail legat de domeniu și fără istoric anterior. Numele de utilizator Gmail tanvisoul9 nu apare în nicio altă înregistrare a editorului npm pe care am putut-o găsi.
Toate cele șase pachete listează același administrator, au fost publicate din același cont și au același package.json șablon standard. Nu există repositoryLa homepage, si nu description mai lung decât o singură linie.
Strategia de denumire este partea interesantă. Spre deosebire de o campanie clasică de confuzie a dependențelor sau typosquat, niciunul dintre aceste nume nu vizează o bibliotecă specifică din amonte. În schimb, ele sunt calibrate să dispară într-o bibliotecă reală. package.json or npm ls ieșire.
| Pachet | Primul publicat | Ultima versiune | versiuni | Rol în Cluster |
|---|---|---|---|---|
| centralogger | 2026-04-01 12:46 UTC | 1.0.9 | 5, de la 1.0.5 la 1.0.9 | Coperta „utilitarului de înregistrare în jurnal” al clusterului; cea mai veche publicare |
| dom-utils-lite | 2026-04-14 07:36 UTC | 1.0.3 | 3 | Copertă generică DOM-helper |
| node-fetch-lite | 2026-04-19 10:22 UTC | 1.0.2 | 3 | Mimică familia de preluare a nodurilor |
| agent conector | 2026-04-25 05:12 UTC | 1.0.0 | 1 | Denumire generică „agent” |
| node-gyp-runtime | 2026-04-25 05:17 UTC | 1.0.0 | 1 | Imită instrumentele de construire a modulelor native |
| node-env-resolve | 2026-04-25 05:21 UTC | 1.0.9 | 10, de la 1.0.0 la 1.0.9 | Pipetă activă; implant complet |
Nume precum centralogger, node-fetch-lite și node-gyp-runtime sunt concepute să pară necontroversate în revizuirea codului. Sună ca lucruri care s-ar afla deja în arborele de dependențe al unui proiect.
Combinate cu un editor nou, neverificat și linkuri lipsă către depozit, acestea formează un model ușor de recunoscut: un actor care introduce nume cu risc redus în registru, apoi iterează rapid pe cel care contează. În acest caz, node-env-resolve a primit zece versiuni în opt zile.
Ce apare pe o cutie pentru dezvoltatori Windows
Lanțul malițios de pe node-env-resolve:1.0.8 este scurt, direct și neobișnuit de bogat în funcții pentru un RAT npm.
Postinstalare: Persistență și agent detașat
package.json declară un singur hook de instalare:
{ "scripts": { "postinstall": "node postinstall.js" } }postinstall.js face trei lucruri în ordine.
Mai întâi, creează un director de instalare în afara arborelui npm. Calea este calculată la momentul execuției în script ca INSTALL_DIRApoi execută o comandă internă execSync('npm install --production --silent ...') în interiorul acestuia pentru a extrage dependențele de execuție ale implantului. Aceasta plasează agentul pe disc undeva într-un fișier manual node_modules auditul nu va găsi.
În al doilea rând, scrie un lansator VBS și îl înregistrează pentru persistența la bootare:
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run \ /v ${AGENT_NAME} \ /t REG_SZ \ /d "wscript.exe \"${vbsPath}\"" /fwscript.exe este Windows Script Host, un fișier binar Microsoft semnat care rulează .vbs fișiere fără o fereastră de consolă. Asta e precisDe aceea este preferat pentru stub-urile de rulare automată.
Există, de asemenea, o potrivire reg delete cale înăuntru src/index.js, ceea ce sugerează că implantul este conceput pentru a fi îndepărtat cu ușurință la comanda operatorului.
În al treilea rând, generează un proces copil detașat:
spawn(node, [path.join(INSTALL_DIR, 'src/index.js')], { detached: true, env: { ...process.env, SERVER_URL } })Două detalii contează aici.
SERVER_URL este citit din mediu. Prin urmare, endpoint-ul C2 este configurabil pentru fiecare implementare și nu este integrat în pachet. Această alegere mică, dar deliberată, anulează majoritatea static-IOC sweep-urilor.
De asemenea, copilul generat moștenește întregul mediu părinte. Prin urmare, orice NPM_TOKEN, AWS_*, GITHUB_TOKEN, sau socketul agentului SSH prezent în shell-ul dezvoltatorului în momentul instalării călătorește în memoria agentului cu viață lungă.
Ce conține agentul
La pachet src/ arborele include trei module ale căror nume singure spun povestea: audioCapture.js, browserHistory.js și systemInfo.js.
Lista de dependențe în timpul execuției, rezolvată în timpul etapei npm install, le coroborează.
Această abordare transformă un incident haotic într-un răspuns controlat.
În loc să reacționeze orbește, echipele operează cu prioritizare clară și remediere rapidă.
| Dependenţă | La ce servește în acest context |
|---|---|
| captură de ecran-desktop | Captură de ecran periodică |
| @nut-tree-fork/nut-js | Automatizare / simulare input mouse și tastatură |
| mai bine-sqlite3 | Citiri directe ale bazelor de date SQLite din istoricul Chrome, Edge și Firefox |
| adm-zip | Gruparea artefactelor colectate înainte de exfiltrare |
| ascuţit | Redimensionarea / comprimarea capturilor de ecran și a artefactelor de imagine |
| socket.io-client | Canal C2 bidirecțional persistent |
| nod-mașină-id | Amprentă digitală stabilă per gazdă pentru urmărirea victimelor |
systemInfo.js Apeluri os.networkInterfaces() pentru amprentare suplimentară înainte de primul far.
De ce captura audio este semnalul remarcabil
Majoritatea RAT-urilor npm pe care le triem în MEW se opresc la furtul secret în timpul instalării. Citesc... ~/.npmrc, citit ~/.aws/credentials, răzui process.env, trimite un POST către un webhook și iese. Aceasta se potrivește unui model economic de tip „smash-and-grab”. Acreditările au un timp de înjumătățire scurt, iar atacatorul trebuie să le monetizeze rapid.
node-env-resolve este diferită ca formă.
Persistența este configurată să supraviețuiască repornirii. Agentul rulează detașat și are o durată lungă de viață sub wscript.exeKitul pe care îl conține este menit să fie prezent pe mașina unui dezvoltator, nu să fie folosit pentru a-l lua și a-l lăsa: un înregistrator de microfon, un driver de tastatură/mouse, ingerarea istoricului complet al browserului, captură de ecran și un canal Socket.IO interactiv înapoi către un C2 configurabil.
Capturarea microfonului, în special, este linia pe care această campanie o depășește, iar majoritatea programelor malware npm nu o depășesc.
O stație de lucru pentru dezvoltatori este, din ce în ce mai mult, și stația de lucru unde dezvoltatorii participă la stand-up-uri, la apeluri cu clienții, la discuții despre design și la bridge-uri de gardă. Un implant care înregistrează microfonul nu are de fapt scopul de a obține token-ul npm al dezvoltatorului. Ci ceea ce spune dezvoltatorul în fața laptopului.
Acest set de capabilități, plus lipsa ofuscării și absența oricărei exfiltrări extravagante în timpul instalării, se citește ca o pre-poziționare pentru acces direcționat, mai degrabă decât ca un furt oportunist de credențiale.
Nu ne bazăm doar pe această afirmație. Observăm profilul operațional.

Cadența iterației de opt zile pe node-env-resolve este cel mai grăitor detaliu din punct de vedere operațional din cronologie.
Aceasta nu este o versiune de tip „dropper de tip „fire and forget”. Editorul întreține în mod activ dropper-ul, ceea ce înseamnă de obicei unul din două lucruri. Fie îl ajustează în funcție de mediile de testare înainte de o implementare mai largă, fie are deja telemetrie de instalare care revine și răspunde la aceasta.
Celelalte cinci pachete nu au înregistrat practic nicio pierdere după publicarea inițială. Aceasta se încadrează într-un model de tipul „etape o dată, părăsire cu numele” pentru clusterul de suport, în timp ce efortul de inginerie se concentrează pe pachetul care face treaba.
Atribuire: Indici mici, fără verdict ferm
Public Osint semnalele sunt subțiri și nu le vom întinde. Ce se observă:
Numele de utilizator Gmail tanvisoul9 seamănă parțial cu un prenume sud-asiatic, „Tanvi”. Acesta este un semnal slab. Utilizatorii Gmail nu reprezintă identitate, iar numele de utilizator de la final soul9 este generic. Nu este sigur să deduci informații geografice doar dintr-o parte locală a unui e-mail.
Stilul codului Node.js este banal: standard apeluri la bibliotecă, cum ar fi os, child_process, spawn și reg addNu există ofuscare, rotație a șirurilor de caractere și logică anti-depanare. Autorul se simte confortabil cu primitivele de registry Windows și orchestrarea proceselor copil-copil detașate, dar nu pare să încerce să folosească tehnici mai discrete pe care le-ar putea folosi în mod plauzibil.
Dependențele sunt complet gata de utilizare și bine cunoscute: screenshot-desktop, nut-js, better-sqlite3 și socket.io-clientNu există niciun protocol personalizat, nicio stivă C2 de la zero și niciun truc nou de persistență dincolo de un manual. Tasta HKCU RunAcesta este un integrator competent, nu un autor de instrumente.
Nu am găsit șiruri de caractere în afara limbii engleze, comentarii încorporate, date regionale sau amprente digitale ale fusului orar generate de compilator în artefactele publicate.
Am verificat dacă există suprapuneri de cod cu campaniile anterioare pe care le urmărim deja, inclusiv Shai Hulud, Owlivion, Buildkite și recentul heibai / claude-code-best Familie de clone Anthropic-CLI. Nu am găsit niciuna: niciun model C2 partajat, nicio machetă de fișiere partajată și nicio idiomă partajată.
Ceea ce nu am spune: că este vorba de un actor statal, un grup cunoscut sau legat geografic de o anumită țară.
Profilul operațional este consistent cu o echipă mică, cu calificare moderată, care se ocupă de supravegherea stațiilor de lucru ale dezvoltatorilor. Probabil este motivat financiar prin utilizarea ulterioară a accesului, dar, eventual, și prin recunoaștere ca serviciu pentru un cumpărător separat.
Două puncte indirecte susțin acest lucru: evitarea mecanismelor de exfiltrare atrăgătoare care ar arde rapid clusterul, cum ar fi boții Telegram, oastify.com, sau canarytokens, și denumirile de pachete intenționat banale, care favorizează instalările silențioase de tip „long-tail” în detrimentul unui vârf scurt de volum mare.
Indicatori de compromis și detectare
| Pachete și editor | |
|---|---|
| Câmp | Valoare |
| editor npm | user0001 |
| Adresă de e-mail a editorului | tanvisoul9@gmail.com, neverificat |
| Pachete | centralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtime, node-env-resolve |
| Confirmat ca fiind rău intenționat | node-env-resolve@1.0.7, node-env-resolve@1.0.8 |
| Artefacte gazdă | |
|---|---|
| Tip | Valoare |
| Cheia de persistență | HKCU\Software\Microsoft\Windows\Versiune curentă\Executare |
| Valoarea persistenței | Nume variabilă; date de forma wscript.exe " \\ .vbs" |
| Instalați cârligul | postinstalare: nodul postinstall.js din manifestul pachetului |
| Module de implant | src/audioCapture.js, src/browserHistory.js, src/systemInfo.js |
| Directorul de pregătire | INSTALL_DIR rezolvat în afara node_modules-ului proiectului; locația este setată de postinstall.js la momentul instalării |
| Reţea | |
|---|---|
| Tip | Valoare |
| Transportul C2 | socket.io-client, canal bidirecțional persistent |
| Punct final C2 | Furnizat agentului prin variabila de mediu SERVER_URL; nu este codificat hard-coded în artefactele publicate |
Note de detectare
Două reguli prind această familie fără a fi nevoie de endpoint-ul C2.
Mai întâi, semnalizați scripturile de postinstalare care efectuează o acțiune internă npm install într-o cale în afara directorului propriu al pachetului. Orice program legitim de descărcare precompilată, cum ar fi node-gyp reconstruiește sau descărcează fișiere binare predefinite, scrie în interiorul pachetului sau în platformă-standard căi de cache cu hash-uri verificate. Nu scrie într-un fișier proaspăt creat INSTALL_DIR în altă parte pe disc.
În al doilea rând, semnalați scripturile postinstalare care au probleme reg add HKCU\…\Run implementate cu wscript.exe ca lansator. Practic, acest lucru nu este niciodată legitim dintr-un pachet npm. Marcați-l și puneți-l în carantină.
O a treia euristică este utilă pentru a identifica următorul pachet frate înainte de confirmare: un editor npm nou, fără SCM verificare, un e-mail Gmail, nu repository câmp și publicarea mai multor nume de pachete scurte, generice, cu aspect de infrastructură, la câteva zile distanță, este suficientă în sine pentru a justifica o revizuire manuală.
Raportat la registrul npm. Vom actualiza această postare când contul de editor va fi eliminat.






