Den 4 augusti 2026 drabbades npm-ekosystemet av en sofistikerad attack mot programvarans leveranskedja, kallad ChainDrop, efter att GitHub-kontot tillhörande en underhållsansvarig för de populära open source-paketen Keyv och Cacheable hade komprometterats . Den resulterande självförökande masken spred sig till över 2 251 versioner av 452 unika paket med cirka 2 miljarder nedladdningar per månad, vilket drabbade organisationer som Deliveroo, Ornikar, OneReach, Picsart, Qlik och ServiceTitan.
Keyv är ett enkelt nyckel-värde-lager för Node.js med stöd för flera backends, medan Cacheable är dess underliggande HTTP-cache-ramverk. Tillsammans fungerar dessa paket som en grundläggande cachinginfrastruktur i hela JavaScript-ekosystemet. Båda paketen underhålls av samma utvecklare, vars GitHub-konto komprometterades av hotaktören.
Angriparen publicerade den första skadliga versionen, keyv@6.0.0, omkring kl. 09:00 UTC den 4 augusti 2026. Skadlig programvaran är en avkomma till ”Mini”-familjen Shai-Hulud, men tillskrivningen till TeamPCP är fortfarande obekräftad. Masken spred sig snabbt genom att samla in npm- och GitHub-token från komprometterade miljöer och använda dem för att publicera ytterligare förgiftade versioner. Socket verifierade 2 251 förgiftade versioner i 452 paket.
Nyttolasten stjäl ett omfattande urval av känslig data, inklusive inloggningsuppgifter för molntjänster, CI/CD-hemligheter, utvecklartoken, AI-konfigurationsfiler och kryptovalutaplånböcker. Den planterar även Claude Code- och Visual Studio Code-hooks för kontinuerlig IDE-baserad körning. Inga CVE-identifierare har tilldelats denna kampanj vid tidpunkten för skrivandet.
Översikt över sårbarheter
Initial åtkomst
Hotaktören komprometterade GitHub-kontot för Keyv-underhållaren, vilket gav direkt push-åtkomst till källkodsrepositorierna för Keyv, Cacheable, cache-manager, flat-cache, file-entry-cache och ett stort antal relaterade paket inom underhållarens monorepo.
Skadlig publicering
Från och med kl. 09:00 UTC införde angriparen IDE-persistenspayloads i Keyv-repositoriet och publicerade därefter keyv@6.0.0 samt efterföljande skadliga versioner. Eftersom paketen byggdes och publicerades via deras legitima GitHub Actions-arbetsflöden innehöll de komprometterade utgåvorna giltig SLSA-ursprungsinformation, vilket gjorde att integritetsverifieringskontrollerna kunde kringgås. Varje förgiftat paket innehöll en post ”preinstall”: ”node setup.mjs” i sin package.json, vilket ledde till att dropparen kördes automatiskt innan någon npm-installation hade slutförts.
Spridning av masken
Malwarens förmåga att sprida sig själv gjorde det möjligt för den att infektera paket som tillhörde andra underhållare vars projekt var beroende av ett tidigare komprometterat paket. Genom att samla in giltiga npm-publiceringstoken från CI/CD-körare och utvecklares arbetsstationer publicerade masken nedströms-paket på nytt med den skadliga nyttolasten injicerad, vilket skapade en kaskadkedja av komprometteringar. Denna mekanism gjorde det möjligt för attacken att undkomma det ursprungliga Keyv/Cacheable-namnområdet och sprida sig över organisationsgränser.
Drabbade paket
De viktigaste komprometterade paketen var:
|
Paketnamn |
Skadliga drabbade versioner |
Verifierat säkert / Återställd ren version |
|
keyv |
6.0.0 (och efterföljande skadliga versioner) |
5.6.0 |
|
flat-cache |
6.1.24 |
6.1.23 |
|
fil-post-cache |
11.1.6 |
11.1.5 (eller tidigare stabil version) |
|
cacheable-request |
13.0.20 |
13.0.19 (eller tidigare stabil version) |
|
cache-manager |
7.2.10 |
7.2.9 |
|
cacheable |
2.5.1 |
2.5.0 (eller tidigare stabil version) |
|
@cacheable/utils |
2.5.1 |
2.5.0 (eller tidigare stabil version) |
|
@cacheable/memory |
2.2.1 |
2.2.0 (eller tidigare stabil version) |
|
@cacheable/node-cache |
3.1.2 |
3.1.1 (eller tidigare stabil version) |
|
@cacheable/net |
2.1.1 |
2.1.0 (eller tidigare stabil version) |
|
ecto |
5.0.1 |
5.0.0 (eller tidigare stabil version) |
Wormen spred sig därefter till paket inom organisationer som Ornikar (bland annat @ornikar/eslint-config-*, @ornikar/prettier-config, @ornikar/babel-preset-* och många fler), Qlik (@nebula.js/nucleus), HubSync (@hubsync/web-sdk-react) och många andra. En fullständig, kontinuerligt uppdaterad lista underhålls av Wiz Research i deras offentliga GitHub-repository.
Viktigt: npm-registret förändrades snabbt under hela incidenten. Kl. 17:40 IST den 4 augusti återställdes tidigare rena versioner som de senaste för minst nio kärnpaket, däribland keyv@5.6.0, flat-cache@6.1.23 och cache-manager@7.2.9. Organisationer måste verifiera exponeringen med hjälp av de exakta paketversionerna som anges i lockfilerna, inte de aktuella registertaggarna.
Analys av skadlig kod
Översikt över nyttolasten
Skadlig programvara distribueras i en tvåstegsarkitektur:
Steg 1 – setup.mjs (Dropper): Detta lätta Node.js-skript fungerar som den initiala nyttolasten. Det kontrollerar om Bun JavaScript-runtime finns och, om så inte är fallet, laddar det ner Bun v1.3.13 från de officiella GitHub-utgåvorna. Därefter överlämnar det exekveringen till huvudpaketet för informationsstöld innan den tillfälliga runtime-katalogen raderas för att minska de forensiska spåren.
Steg 2 – Math_Symbol.js / math_init.js (infostealer): Ett kraftigt förvrängt, kompilerat paket på 727 680 byte som körs via Bun-runtime-miljön. Detta är den centrala motorn för insamling av inloggningsuppgifter. Båda filnamnen (Math_Symbol.js och math_init.js) har observerats i det vilda och innehåller identisk funktionalitet med samma SHA-1-hash.
Mål för insamling av inloggningsuppgifter
Infostealern inventerar och exfiltrerar systematiskt:
- Molninloggningsuppgifter: AWS-åtkomstnycklar, SSM Parameter Store-värden (med WithDecryption: true), AWS Secrets Manager-hemligheter, Azure- och GCP-inloggningsuppgifter
- CI/CD-hemligheter: GitHub Actions-hemligheter, inklusive extrahering av ”isSecret”:true-värden från minnet hos en egenhostad runner, GitHub-workflow-tokens
- Utvecklartoken: GitHub Personal Access Tokens (prefixen ghp_, gho_, ghs_), npm-publiceringstoken (prefixet npm_), varje token valideras i realtid mot registry.npmjs.org/-/whoami före exfiltrering
- Infrastrukturhemligheter: Kubernetes-hemligheter från alla tillgängliga namnutrymmen, HashiCorp Vault-tokens och KV-hemligheter, Terraform-autentiseringsuppgifter, SSH-nycklar, databasanslutningssträngar
- AI- och IDE-konfiguration: Claude API-konfigurationsfiler, inloggningsuppgifter för AI-relaterade tjänster
- Kryptovalutaplånböcker: Lokala plånboksfiler och nycklar
- Inloggningsuppgifter för tjänster: Stripe, Slack, Twilio och andra API-nycklar från tredjepartsleverantörer
- Hela processmiljön: Alla miljövariabler från den komprometterade processen
Persistensmekanismer
Keyv-repositoriet behöll separata kopplingar till Claude Code (.claude/settings.json) och Visual Studio Code (.vscode/). Dessa persistensmekanismer på IDE-nivå kan köra nyttolasten så snart en användare litar på arbetsytan eller godkänner projektkonfigurationen, vilket ger en sekundär körväg oberoende av npm install-livscykelskript.
Skadlig programvara installerar även en bevakare för återkallande av autentiseringsuppgifter – en fälla som utlöser en lokal hanterare som tillhandahålls av angriparen när token byts ut. De som hanterar incidenten måste ta bort denna bevakare innan de byter ut några autentiseringsuppgifter.
Kommando och kontroll
Skadlig programvaran hämtar sina C2-domäner från ett smart kontrakt på Ethereum (StringListStore) med hjälp av ett eth_call istället för att bädda in dem i nyttolasten. Denna blockkedjebaserade C2-upplösning gör det möjligt för operatören att uppdatera infrastrukturen utan att behöva modifiera den skadliga programvaran. Historiken på blockkedjan visar att kontraktet ursprungligen konfigurerades med tre domäner innan det uppdaterades för att endast returnera npm-cache[.]com. Kontraktets ägare finansierades av en adress som tidigare flaggats för bedräglig verksamhet.
Exfiltrering
Stulna data krypteras med ett hybridsystem bestående av AES-256 och RSA-4096 och exfiltreras sedan via två kanaler:
- Offentliga GitHub-repositorier som skapats under komprometterade identiteter, med beskrivningen ”Shai-Hulud: Here We Go Again”
- Domänen npm-cache[.]com
De första commit-uppdateringarna till utläckningsrepositorierna innehåller hottexposten: ”IfYouBlockThisAPIKeyItWillCrashTheLiveProductionServersOfAllThirdPartyClients.”
Kända indikatorer på intrång (IoC)
|
Kategori |
Indikator |
Beskrivning |
|
Domän |
npm-cache[.]com |
Primär C2- och dataexfiltreringsdomän; levereras via Cloudflare |
|
Domän |
registry[.]npmjs[.]org |
Endpunkt för tokenvalidering som missbrukas för verifiering av inloggningsuppgifter i realtid före exfiltrering |
|
Domän |
eth-mainnet[.]nodereal[.]io |
Ethereum RPC-ändpunkt som används för att hämta C2-domäner baserade på smarta kontrakt |
|
Domän |
go[.]getblock[.]io |
Ethereum RPC-ändpunkt som används för hämtning av C2-domäner baserat på smarta kontrakt |
|
Domän |
eth[.]llamarpc[.]com |
Ethereum RPC-ändpunkt som används för att hämta C2-domäner baserade på smarta kontrakt |
|
Domän |
pypi-get[.]com |
Ytterligare infrastruktur som kontrolleras av angriparen |
|
Domän |
js-mirror[.]com |
Ytterligare infrastruktur som kontrolleras av angriparen |
|
IPv4 |
104[.]21[.]35[.]216 |
Cloudflare-IP kopplad till npm-cache[.]com |
|
IPv4 |
172[.]67[.]167[.]200 |
Cloudflare-IP kopplad till eth[.]llamarpc[.]com |
|
IPv4 |
185[.]44[.]207[.]215 |
IP kopplad till go[.]getblock[.]io ETH RPC |
|
IPv4 |
35[.]175[.]164[.]77 |
AWS-IP kopplad till eth-mainnet[.]nodereal[.]io |
|
Filnamn |
Math_Symbol.js |
Förvrängd infostealer-payload (727 680 byte); distribuerad via preinstall-skript i npm-paket |
|
Filnamn |
math_init.js |
Variant av infostealer-payloaden med identisk funktionalitet |
|
Filnamn |
setup.mjs |
Stage-1-dropper; hämtar Bun-runtime och utlöser körning av infostealer |
|
Filhash (SHA-1) |
35a672cf34b996b91f3e1c28cbf3a05a37e036e4 |
Math_Symbol.js / math_init.js – infostealer-nyttolast |
|
Filhash (SHA-1) |
686aa40d0fc22c8d569494543a0f891f359f2f99 |
setup.mjs i katalogen .claude (Claude Code hook) |
|
Filhash (SHA-1) |
f525d52ceb966516686b482d3dc0137028cc6a63 |
setup.mjs finns i katalogen .vscode (VS Code-hook) |
|
Användaragent |
Bun/1.3.13 |
HTTP-user-agent-sträng som används vid nedladdning av Bun-runtime och C2-kommunikation |
|
Filsystemväg |
/tmp/bun-dl-*/ |
Tillfällig katalog som används för nedladdning och mellanlagring av Bun-runtime |
|
Filsystemets sökväg |
node_modules/keyv/Math_Symbol.js |
Platsen för infostealer-payloaden i det installerade paketträdet |
|
Sträng |
Shai-Hulud: Here We Go Again |
Beskrivning av GitHub-repositoriet som används för exfiltreringsrepositorier |
|
Sträng |
Om du blockerar den här API-nyckeln kommer det att krascha live-produktionsservrarna hos alla tredjepartsklienter |
Hotfull sträng i de första exfiltrerings-commitsen |
Detekteringar och hotjakt
Säkerhetsteam bör implementera följande detekteringsåtgärder:
- Beroendegranskning: Skanna alla package-lock.json-, yarn.lock-, pnpm-lock.yaml- och bun.lockb-filer för att hitta de drabbade paketen och versionerna. Lita inte på aktuella registertaggar – använd uteslutande de versioner som anges i låsfilerna.
- Filsystemindikatorer: Sök igenom utvecklingsarbetsstationer, CI/CD-körare och byggservrar efter förekomsten av Math_Symbol.js, math_init.js och setup.mjs i node_modules-träd och tillfälliga kataloger som matchar /tmp/bun-dl-*/.
- Nätverksövervakning: Skicka varningar vid utgående anslutningar och DNS-förfrågningar till npm-cache[.]com, pypi-get[.]com, js-mirror[.]com samt de Ethereum RPC-ändpunkter som anges i IOC:erna ovan. Övervaka efter användaragentsträngen Bun/1.3.13.
- GitHub-granskning: Granska organisationer för oväntade offentliga repositorier med beskrivningen ”Shai-Hulud: Here We Go Again” eller commit som innehåller hotsträngen.
- Övervakning av preinstall-skript: Granska package.json-filer i alla projekt för oväntade preinstall-skriptposter som refererar till setup.mjs.
- Förtroende för IDE-arbetsytor: Kontrollera om det finns obehöriga .claude/settings.json- och .vscode/-konfigurationer som kan ladda externa nyttolaster.
Åtgärder och avhjälpande åtgärder
Omedelbara åtgärder
- Identifiera och ta bort drabbade versioner: Granska alla miljöer och ta bort alla installationer av de skadliga paketversionerna. Uppgradera till rena, verifierade versioner.
- Ta bort övervakaren för återkallande av autentiseringsuppgifter först: Rotera inte token innan du har tagit bort skadlig programvara. Den skadliga koden installerar en övervakare som aktiveras vid återkallande av token. Om du roterar autentiseringsuppgifter i förtid kan en hanterare som tillhandahålls av angriparen köras. Ta bort den skadliga programvaran från drabbade system innan du fortsätter med rotationen av autentiseringsuppgifter.
- Utgå från att alla autentiseringsuppgifter har komprometterats: Om någon drabbad version har installerats ska alla autentiseringsuppgifter som är tillgängliga i den miljön behandlas som stulna. Detta inkluderar molnautentiseringsuppgifter, npm-token, GitHub PAT:er, SSH-nycklar, CI/CD-hemligheter, databasautentiseringsuppgifter och API-nycklar från tredje part.
- Rotera alla exponerade inloggningsuppgifter: Efter att skadlig programvara har tagits bort ska följande roteras: alla npm-publiceringstoken, GitHub Personal Access Tokens och OAuth-token, AWS IAM-åtkomstnycklar, autentiseringsuppgifter för Azure- och GCP-tjänsteprinciper, Kubernetes-tjänstekontotoken, HashiCorp Vault-token, databaslösenord, SSH-nycklar och API-nycklar från tredjeparter (Stripe, Slack, Twilio osv.).
- Återkalla och utfärda nya npm-/GitHub-token: Använd npm- och GitHub-administratörskonsolerna för att tvinga fram återkallandet av alla potentiellt exponerade token. Generera nya token med minsta möjliga behörighetsomfång.
Systemåterställning
- Återuppbygg de drabbade systemen: Behandla alla utvecklingsarbetsstationer, CI/CD-körare eller byggservrar där ett skadligt paket har installerats som potentiellt komprometterade. Återuppbygg från en bild eller ögonblicksbild som bekräftats vara ren.
- Rensa lokala cacher: Rensa npm-cachen (npm cache clean --force), Yarn-cachen, pnpm-lagret och Bun-cachen för att eliminera cachelagrade skadliga paket.
- Ta bort och återskapa virtuella miljöer: Nöj dig inte med att bara nedgradera drabbade paket. Ta bort node_modules-katalogerna och återskapa de virtuella Python-miljöerna helt och hållet.
Granskning av moln- och källkodsmiljöer
- Granska molnmiljöer: Granska AWS CloudTrail, Azure Activity Logs och GCP Audit Logs för obehöriga API-anrop som härrör från tidsperioden då paketet installerades. Kontrollera om det skett oväntad skapande av IAM-användare eller -roller, åtkomst till SSM Parameter Store med dekryptering samt åtkomst till Secrets Manager.
- Granska GitHub-granskningsloggar: Undersök organisationens granskningsloggar för oväntad skapande av repositorier, generering av token och ändringar i arbetsflöden.
- Sök efter repositorier för dataexfiltrering: Sök efter offentliga repositorier som skapats under din organisations identiteter med beskrivningen ”Shai-Hulud: Here We Go Again”.
Säkring av leveranskedjan
- Fäst beroenden: Använd exakt versionsfästning i alla package.json-filer och lägg in låsfiler i versionshanteringen.
- Uppgradera till npm 12: npm 12 blockerar som standard icke-godkända livscykelskript för beroenden, vilket förhindrar automatisk körning av preinstall-skript. Tidigare npm-klienter förblir sårbara.
- Tillämpa SLSA och OIDC: Kräv SLSA-härkomstintyg och verifiera dem vid byggtillfället. Observera dock att denna kampanj visade att härkomst i sig inte är tillräckligt när angriparen kontrollerar byggpipeline – härkomst måste kombineras med identitetsverifiering.
- Aktivera tillåtna listor för beroenden: Begränsa tillåtna paketkällor och versioner genom verktyg som Socket, Semgrep Supply Chain eller policyerna i ditt artefaktregister.
- Implementera verifiering av paketintegritet: Använd npm-auditsignaturer och verifiera registrets integritetshashar där detta stöds.
- Aktivera MFA på alla underhållarkonton: Kräv hårdvarubaserad MFA för alla npm- och GitHub-konton med publiceringsbehörighet.
- Blockera skadliga domäner: Lägg till de IOC:er som anges ovan i dina blockeringslistor för nätverksgränsen och dina DNS-filtreringslösningar.
Om du är orolig för någon av de hot som beskrivs i detta meddelande eller behöver hjälp med att avgöra vilka åtgärder du bör vidta för att skydda dig mot de mest väsentliga hoten som din organisation står inför, vänligen kontakta din kundansvarige eller hör av dig till oss för att ta reda på hur du kan skydda din organisation.