Hijacked npm packages steal cloud keys from developers

Someone took over a GitHub maintainer account and used it to publish poisoned versions of 42 npm packages, among them keyv, a caching library that sits deep inside a great many JavaScript projects. The malicious releases go looking for secrets: cloud credentials, infrastructure and developer secrets, AI tool configuration files and cryptocurrency wallets.

Wiz Research is actively investigating the campaign and says the account takeover led directly to the malicious publishes. In an analysis by Merav Bar, the company says the attacker began at 09:00 UTC by pushing payloads into the keyv repository that persist inside developers' code editors, then published a new version of keyv carrying the payload shortly after. Every affected version shipped the same code. Wiz describes these as initial findings and says it will add technical detail, indicators and newly identified packages as the investigation continues.

What's affected

Forty two package versions are listed as malicious. The ones most likely to be sitting in a build somewhere are keyv 6.0.0, @cacheable/utils 2.5.1, cacheable-request 13.0.20 and cache-manager 7.2.10. The rest are mostly project tooling and embed libraries: a large block of @ornikar/ shared configs (eslint, babel, prettier, stylelint, postcss and related presets), four @qlik/embed packages, @nebula.js/nucleus 0.5.1, @hubsync/web-sdk-react 6.3.7, http-metrics-middleware 2.2.2 and both picasso plugins at 2.11.6. Anything that pulled a fresh copy of those during the window is suspect.

What the malware takes

Wiz's analysis indicates the payload is a descendant of the "Mini" Shai-Hulud malware family, sharing similarities with the TeamPCP and antv supply chain campaigns. Beyond credential theft on the developer's own machine, it attempts to harvest secrets from CI/CD environments, identify build runners and enumerate cloud environments, which is how a single poisoned install turns into access to the infrastructure behind it. Stolen data is exfiltrated through GitHub repositories created under compromised identities, carrying the description "Shai-Hulud: Here We Go Again", matching Shai-Hulud code that was previously open-sourced. The initial commits also carry a new intimidation string aimed at anyone who might revoke a stolen key: IfYouBlockThisAPIKeyItWillCrashTheLiveProductionServersOfAllThirdPartyClients.

The lineage matters. IntelFusions covered an earlier Shai-Hulud variant tuned to slip past AI security scanners in June, and the TeamPCP crew turned up again in July when a ransomware group announced a partnership with it. This is a toolkit with a maintained code base and more than one operator.

What you should do

Wiz's guidance is blunt: find and remove the affected versions from development, build and CI/CD environments, and treat any system that installed one as potentially compromised, rebuilding rather than cleaning. Rotate everything the payload could have reached, including cloud credentials, GitHub tokens, SSH keys, Kubernetes configurations, Terraform credentials and other developer secrets. Review cloud and source code environments for unauthorized access following the install. Longer term, dependency allowlisting, package integrity verification and provenance controls are the defences that would have limited the blast radius.

Indicators of compromise

Defanged here. The exfiltration domain is npm-cache[.]com (104[.]21[.]35[.]216). The malware also reaches Ethereum RPC endpoints at eth-mainnet.nodereal[.]io (35[.]175[.]164[.]77), go.getblock[.]io (185[.]44[.]207[.]215) and eth.llamarpc[.]com (172[.]67[.]167[.]200). On disk, look for node_modules/keyv/Math_Symbol.js and directories matching /tmp/bun-dl-*/, plus setup.mjs files dropped into .claude and .vscode folders. The SHA-1 for Math_Symbol.js is 35a672cf34b996b91f3e1c28cbf3a05a37e036e4; the .claude and .vscode copies of setup.mjs are 686aa40d0fc22c8d569494543a0f891f359f2f99 and f525d52ceb966516686b482d3dc0137028cc6a63 respectively.

The pattern is now familiar: a maintainer account, not a package registry, is the weak link. It was a GitHub Actions flaw last month, and a hijacked identity this time.

This briefing is provided by IntelFusions for informational and defensive purposes only. It is based on sources assessed to be reliable at the time of writing, and analytic judgments carry the confidence levels indicated. Indicators of compromise are defanged; re-arm them only in controlled environments. IntelFusions is not affiliated with the organizations named and makes no warranty as to completeness or accuracy.

Read the full analysis on IntelFusions