DevTap npm Typosquatting Attack

DevTap npm Typosquatting-attack: Sex skadliga paket riktar sig mot utvecklarnas arbetsstationer

TL; DR

Mellan 1 april och 3 maj 2026, en enda npm-utgivare, user0001, registrerad med den overifierade Gmail-adressen tanvisoul9@gmail.com, lanserade i tysthet sex paket med avsiktligt intetsägande, infrastrukturklingande namn: centralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtimeoch node-env-resolve.

De två senaste versionerna av node-env-resolve, 1.0.7 och 1.0.8, flaggades av Xygenis system för tidig varning mot malware (MEW) den 2 maj och bekräftades som skadliga den 3 maj.

Implantatet är ovanligt för vad det inte är: det finns inga Telegram-botar, inga OAST-återuppringningar, inga förvirring, och inget försök att hämta AWS-inloggningsuppgifter vid installationstillfället. Istället, postinstall.js planterar en Windows boot-persistence-post med hjälp av en HKCU Run-tangent som startar wscript.exe mot en VBS-stub. Sedan skapar den en fristående Node.js-agent som paketerar moduler för mikrofoninspelning, stöld av webbläsarhistorik, skärmdumpar och simulering av mus/tangentbord.

Vi kallar detta kluster DevTap, efter att kittet lämnar det körs på en utvecklares maskin.

Alla sex paketen var tillgängliga på npm i skrivande stund. Vi har skickat in dem till registrets kanal för missbruk. Försvarare bör hämta alla installationer från utgivaren i väntan på borttagning.

Klustret: Sex paket, en utgivare

Utgivarens konto user0001 är overifierad. Den har ingen SCM verifiering, ingen domänbunden e-post och ingen tidigare historik. Gmail-användaren tanvisoul9 förekommer inte i någon annan npm-utgivares post vi kunde hitta.

Alla sex paketen listar samma utvecklare, publicerades från samma konto och delar samma package.json standardstandard. Det finns ingen repository, Nr homepage, och nej description längre än en enda rad.

Namngivningsstrategin är den intressanta delen. Till skillnad från en klassisk beroendeförvirrings- eller typosquat-kampanj riktar sig inget av dessa namn mot ett specifikt uppströmsbibliotek. Istället är de kalibrerade för att försvinna in i en verklig package.json or npm ls utgång.

PaketFörst publiceradSenaste versionenversionerRoll i klustret
centrallogger2026-04-01 12:46 UTC1.0.95, från 1.0.5 till 1.0.9Klustrets omslag till "loggverktyget"; tidigaste publicering
dom-utils-lite2026-04-14 07:36 UTC1.0.33Generiskt DOM-hjälpskydd
node-fetch-lite2026-04-19 10:22 UTC1.0.23Härmar node-fetch-familjen
kontaktagent2026-04-25 05:12 UTC1.0.01Generiskt namn "agent"
node-gyp-runtime2026-04-25 05:17 UTC1.0.01Efterliknar verktyg för byggande av nativa moduler
nod-miljö-lös2026-04-25 05:21 UTC1.0.910, från 1.0.0 till 1.0.9Aktiv dropper; fullständigt implantat

Namn som centralogger, node-fetch-liteoch node-gyp-runtime är utformade för att se okontroversiella ut vid kodgranskning. De låter som saker som redan skulle finnas i ett projekts beroendeträd.

Kombinerat med en ny, overifierad utgivare och saknade länkar till arkiven bildar de ett igenkännbart mönster: en aktör som sår lättanvända namn i registret och sedan snabbt itererar på det som är viktigt. I det här fallet, node-env-resolve fick tio versioner på åtta dagar.

Vad som hamnar på en Windows Dev Box

Den illvilliga kedjan på node-env-resolve:1.0.8 är kort, direkt och ovanligt funktionsrik för att vara en npm RAT.

Efterinstallation: Persistens och avskild agent

package.json deklarerar en enda installationshook:

{ "scripts": { "postinstall": "node postinstall.js" } }

postinstall.js gör tre saker i tur och ordning.

Först placerar den en installationskatalog utanför npm-trädet. Sökvägen beräknas vid körning i skriptet som INSTALL_DIRSedan körs en intern execSync('npm install --production --silent ...') inuti den för att hämta implantatets runtime-beroenden. Detta placerar agenten på disk någonstans i en manual node_modules revisionen kommer inte att hitta.

För det andra skriver den en VBS-startare och registrerar den för startpersistens:

reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run \     /v ${AGENT_NAME} \     /t REG_SZ \     /d "wscript.exe \"${vbsPath}\"" /f

wscript.exe är Windows Script Host, en signerad Microsoft-binärfil som körs .vbs filer utan ett konsolfönster. Det är förberettcisvarför det är föredraget för autorun-stubbar.

Det finns också en matchning reg delete väg inuti src/index.js, vilket tyder på att implantatet är utformat för att enkelt kunna tas bort på operatörens kommando.

För det tredje skapar det en fristående underprocess:

spawn(node, [path.join(INSTALL_DIR, 'src/index.js')], {   detached: true,   env: { ...process.env, SERVER_URL } })

Två detaljer är viktiga här.

SERVER_URL läses från miljön. Som ett resultat är C2-slutpunkten konfigurerbar per driftsättning och är inte inbyggd i paketet. Det lilla men avsiktliga valet omintetgör de flesta statiska IOC-svep.

Dessutom ärver det skapade barnet hela föräldramiljön. Därför, alla NPM_TOKEN, AWS_*, GITHUB_TOKEN, eller SSH-agent-socketen som finns i utvecklarskalet vid installationstillfället, färdas till den långlivade agentens minne.

Vad agenten skickar med

Den buntade src/ trädet innehåller tre moduler vars namn ensamma berättar historien: audioCapture.js, browserHistory.jsoch systemInfo.js.

Listan över runtime-beroenden, löst under den stegvisa npm install, bekräftar dem.

Denna metod förvandlar en kaotisk incident till en kontrollerad respons.

Istället för att reagera blint arbetar team med tydlig prioritering och snabb åtgärd.

DependencyVad det är till för i detta sammanhang
skärmdump-skrivbordRegelbunden skärmdumpning
@nötträdgaffel/nöt-jsMus- och tangentbordsautomation / inmatningssimulering
bättre-sqlite3Direktläsning av Chrome-, Edge- och Firefox History SQLite-databaser
adm-postkodBuntning av insamlade artefakter före exfiltrering
skarpÄndra storlek på/komprimera skärmdumpar och bildartefakter
socket.io-klientPersistent dubbelriktad C2-kanal
nod-maskin-idStabilt fingeravtryck per värd för spårning av offer

systemInfo.js samtal os.networkInterfaces() för ytterligare fingeravtryck före den första beaconen.

Varför ljudinspelningen är den enastående signalen

De flesta npm RAT:er som vi triagerar i MEW stoppar vid hemlig stöld under installationstid. De läser. ~/.npmrc, läs ~/.aws/credentials, skrapa process.env, POST till en webhook och avsluta. Det passar en ekonomisk modell med "smash-and-grab"-funktion. Autentiseringsuppgifter har en kort halveringstid och angriparen måste tjäna pengar snabbt.

node-env-resolve är olika i formen.

Persistensen är konfigurerad för att överleva omstart. Agenten körs fristående och långlivad under wscript.exeKitet den bär är till för att vara där på en utvecklares maskin, inte för att ta och lämna: en mikrofoninspelare, en tangentbords-/musdrivrutin, fullständig webbläsarhistorikinmatning, skärmdump och en interaktiv Socket.IO-kanal tillbaka till en konfigurerbar C2.

Speciellt mikrofoninspelning är den gräns som den här kampanjen korsar, vilket de flesta npm-skadliga program inte gör.

En utvecklararbetsstation är i allt större utsträckning också den arbetsstation där utvecklare tar emot stående samtal, kundsamtal, designdiskussioner och jourhavande samtal. Ett implantat som spelar in mikrofonen är egentligen inte ute efter utvecklarens npm-token. Det är ute efter vad utvecklaren säger framför den bärbara datorn.

Den uppsättningen funktioner, plus avsaknaden av obfuskation och avsaknaden av någon flashig exfiltrering under installationsprocessen, läser som förpositionering för riktad åtkomst snarare än opportunistisk stöld av autentiseringsuppgifter.

Vi hävdar inte att det är orsaken enbart utifrån detta. Vi noterar den operativa profilen.

npm typosquatting-attack - DevTab

Åtta dagars iterationskadens på node-env-resolve är den mest operativt talande detaljen i tidslinjen.

Detta är inte en "avfyra och glöm"-dropp. Utgivaren underhåller aktivt droppern, vilket vanligtvis innebär en av två saker. Antingen justerar de den mot testmiljöer innan bredare distribution, eller så har de redan installerad telemetri som kommer tillbaka och svarar på den.

De övriga fem paketen såg i praktiken ingen kundbortfall efter sin första publicering. Det passar in i ett mönster där "en gång i fasen lämnas namngiven" för stödklustret, medan ingenjörsarbetet fokuserar på det paket som gör jobbet.

Tillskrivning: Små ledtrådar, ingen fast dom

offentliga OSINT Signalerna är tunna, och vi kommer inte att tänja på dem. Vad som är observerbart:

Gmail-användaren tanvisoul9 liknar delvis ett sydasiatiskt förnamn, ”Tanvi”. Detta är en svag signal. Gmail-användare är inte identitet, och det efterföljande namnet soul9 är generiskt. Det är inte säkert att härleda geografi enbart från en lokal del av ett e-postmeddelande.

Kodstilen är anmärkningsvärd Node.js: standard bibliotekssamtal som t.ex. os, child_process, spawnoch reg addDet finns ingen obfuskation, ingen strängrotation och ingen anti-felsökningslogik. Författaren är bekväm med Windows-registerprimitiver och orkestrering av fristående barnprocesser, men verkar inte sträva efter mer smygande hantverk som de rimligen skulle kunna använda.

Beroenden är helt standard och välkända: screenshot-desktop, nut-js, better-sqlite3och socket.io-clientDet finns inget anpassat protokoll, ingen från grunden rullad C2-stack och inget nytt persistensknep utöver en lärobok. HKCU Run-nyckelDetta är en kompetent integratör, inte en verktygsförfattare.

Vi hittade inga icke-engelska strängar, inbäddade kommentarer, språkdata eller fingeravtryck från tidszoner från kompilatorn i de publicerade artefakterna.

Vi kontrollerade kodöverlappningar med tidigare kampanjer som vi redan spårar, inklusive Shai Hulud, Owlivion, Buildkite, och den senaste heibai / claude-code-best Klonfamiljen Anthropic-CLI. Vi hittade inga: inga delade C2-mönster, inga delade fillayouter och inga delade idiom.

Vad vi inte skulle säga: att detta är en statlig aktör, en känd grupp eller geografiskt knuten till något specifikt land.

Den operativa profilen överensstämmer med ett litet, måttligt skickligt team som utför övervakning på utvecklararbetsstationer. Det är sannolikt ekonomiskt motiverat genom nedströmsanvändning av åtkomsten, men möjligen också rekognoscering-som-en-tjänst för en separat köpare.

Två indirekta punkter stöder detta: undvikandet av uppmärksamhetsfångande exfiltreringsmekanismer som snabbt skulle bränna klustret, såsom Telegram-botar, oastify.com, eller canarytokens, och de avsiktligt intetsägande paketnamnen, som föredrar tysta long-tail-installationer framför en kort topp i hög volym.

Indikatorer för kompromiss och upptäckt

Paket och utgivare
FältVärderar
npm-utgivareuser0001
Utgivarens e-postadresstanvisoul9@gmail.com, overifierad
Paketcentralogger, dom-utils-lite, node-fetch-lite, connector-agent, node-gyp-runtime, node-env-resolve
Bekräftat skadlignode-env-resolve@1.0.7, node-env-resolve@1.0.8
Värdartefakter
TypVärderar
PersistensnyckelHKCU\Programvara\Microsoft\Windows\Aktuell version\Kör
PersistensvärdeVariabelnamn; data av formen wscript.exe " \\ .vbs"
Montera krokenpostinstall: noden postinstall.js i paketmanifestet
Implantatmodulersrc/audioCapture.js, src/browserHistory.js, src/systemInfo.js
Staging-katalogINSTALL_DIR löstes utanför projektets node_modules; platsen angavs av postinstall.js vid installationstillfället.
nätverks
TypVärderar
C2-transportsocket.io-klient, ihållande dubbelriktad kanal
C2-slutpunktTillhandahålls agenten via miljövariabeln SERVER_URL; inte hårdkodad i publicerade artefakter

Detektionsanteckningar

Två regler fångar denna familj utan att behöva C2-slutpunkten.

Först, flagga postinstall-skript som utför en intern npm install till en sökväg utanför paketets egen katalog. Alla legitima förbyggda nedladdare, som till exempel node-gyp ombyggnader eller förbyggda binära nedladdare, skriver inuti paketet eller till plattform-standard cachesökvägar med verifierade hash-värden. Den skriver inte till en nyligen skapad INSTALL_DIR någon annanstans på disken.

För det andra, flagga postinstall-skript som utlöser problem reg add HKCU\…\Run med wscript.exe som startprogram. Detta är i princip aldrig legitimt från ett npm-paket. Flagga och karantänera det.

En tredje heuristik är användbar för att identifiera nästa syskonpaket innan det bekräftas: en ny npm-utgivare utan SCM verifiering, en Gmail-e-postadress, nej repository fält, och flera korta, generiska, infrastrukturklingande paketnamn som publiceras inom några dagar efter varandra, är i sig tillräckligt för att motivera manuell granskning.

Rapporterat till npm-registret. Vi kommer att uppdatera det här inlägget när utgivarkontot har tagits bort.

sca-tools-programvara-verktyg-för-kompositionsanalys
Prioritera, åtgärda och säkra dina programvarurisker
Skaffa ditt gratiskonto.
Inga kreditkort krävs.

Säkra din programvaruutveckling och leverans

med Xygeni-produktsviten