Seks npm-pakker deler samme DPRK-laster, og tre av dem var kapret
Fjern seks npm-pakker som alle kjører samme DPRK-koblede laster og henter adressen til kontrollserveren sin fra en Ethereum-transaksjon.
Tre av de seks pakkene Sonatype Research Labs identifiserte 10. august 2026 var legitime biblioteker som ble kapret: @kolbo/mcp 1.57.1, agentgui 1.0.1127 og godot-kit 1.0.1786316795. Sonatype sporer den gruppen som sonatype-2026-005899. De tre andre, envpack-conf 1.0.1, postcss-initial-provider 3.0.4 og tailwindcss-motion-advanced 1.0.1, ble publisert med skadevaren inne fra første versjon og spores separat som sonatype-2026-005901. Ifølge Sonatypes Adam Reynolds faller pakkene i disse to gruppene. I de kaprede pakkene ble lasteren lagt til på slutten av en fil som allerede fantes i det legitime biblioteket, som siste linje i database.js i agentgui.
Mekanismen er poenget her. Når lasteren kjører, spør den Ethereum om en utgående transaksjon fra en angriperkontrollert lommebok og leser bytes ut av mottakeradressen i den transaksjonen. Bytene dekodes til to IPv4-adresser, som skadevaren behandler som primær og sekundær kontrollserver. Transaksjonen fungerer som en dead drop: den forteller skadevaren hvor den skal koble seg til videre, uten at angriperen trenger et domene som kan tas ned.
Sonatype beskriver implementasjonen som mer omfattende enn NullReceiver-oppførselen OpenSourceMalware dokumenterte i npm-pakkene bianira-ui og fluid-type-ui. Denne varianten kan spørre flere Ethereum-RPC-leverandører, kjøre forespørslene i kappløp mot hverandre, bruke batchede JSON-RPC-kall og falle tilbake på Blockscout-API-et hvis ingen av delene finner transaksjonen. Fire veier leder til samme svar, så det holder ikke å blokkere én RPC-leverandør. Lommeboka er den samme som i aktivitet OpenSourceMalware har tilskrevet Contagious Interview, DPRK-kampanjen som knyttes til Lazarus-gruppen.
Etter at kontrollserveren er funnet, henter lasteren to trinn til fra endepunktene /0x/cls og /0x/ls. Klarer den ikke å hente lasten gjennom et vanlig HTTP GET-svar, sender den en HEAD-forespørsel og plukker den ut av responsheaderen X-Payload-B64 i stedet. Innholdet base64- og XOR-dekodes før kjøring: lasten fra /0x/cls kan kjøres direkte i den pågående Node-prosessen med eval(), mens nedlastede trinn også kan startes som frittstående Node-barneprosesser.
For deg som bygger er @kolbo/mcp den ubehagelige detaljen. MCP-servere installeres i dag på omtrent samme løse tillit som nettleserutvidelser, og en kapret versjon av en pakke du allerede har i lockfilen ser ut som en helt vanlig patch-oppdatering. Sonatype påpeker at nettopp de tre kaprede pakkene er lettest å overse, fordi koden kom inn gjennom navn utviklerne allerede kjente igjen og stolte på.
Hva bør du gjøre?
- Søk i lockfilene etter alle seks pakkenavnene og de eksakte versjonene over, ikke bare pakkenavnet, og fjern treff.
- Se etter utgående trafikk mot Ethereum-RPC-endepunkter og Blockscout fra byggeservere og utviklermaskiner. Et byggesteg har ingen grunn til å snakke med en blokkjede.
- Behandle et treff som et kompromittert miljø og let etter etterfølgende JavaScript-kjøring, ikke bare avinstaller pakken.
KI-kuratert — innholdet er generert av KI-agenter basert på originalkilden.