33 malicious npm packages drop off-registry credential harvesters
TL;DR - PhantomRaven Wave 5 is live: 33 poisoned npm packages use a self-referencing HTTP dependency to pull a shared dropper package from attacker infrastructure and execute a credential harvester via preinstall. C2 was still up at time of publication. If you installed any of the listed packages, rotate everything accessible from that machine.
What happened
npm runs lifecycle hooks - including preinstall - automatically during npm install. That behaviour is the entire attack surface here.
Mend identified a fifth wave of the PhantomRaven campaign comprising 33 malicious packages backed by new C2 infrastructure. The central trick is what Mend calls a Remote Dynamic Dependency: each poisoned package lists itself as a dependency, but via an http:// URL pointing at attacker-controlled hosting rather than the registry. npm dutifully fetches a second-stage tarball from outside npmjs.org.
The execution chain:
- Stage 0: Developer installs a malicious package.
- Stage 1: npm resolves the self-referencing HTTP dependency and fetches a shared dropper package -
idle-style-xi- from the C2. - Stage 2:
idle-style-xifires apreinstallhook (node index.js), fetches a short-lived token, downloadsroute.js, writes it to/tmp/collector-<timestamp>.js, executes it viarequire(), then deletes the file. - Exfiltration: Harvested credentials are sent via HTTP POST to
pack[.]nppacks[.]com/mozbra.php.
Hosting the payload off-registry is deliberate. Tools that only scan published npm packages miss it entirely. The hook executes before your code runs, on the machine doing the install - developer laptop or CI runner.
Mend explicitly names the targeted ecosystems: DeFi/crypto, cloud infrastructure, and AI/LLM developers.
Who is impacted
- Any developer workstation or CI runner that installed one of the Wave 5 packages listed by Mend.
- Environments where npm lifecycle scripts run (the default), particularly where cloud credentials,
GITHUB_TOKEN, SSH keys, or CI secrets are present. - Teams working in DeFi/crypto, cloud infrastructure, or AI/LLM tooling - the segments Mend identifies as explicitly targeted.
What to do now
- Assume compromise on any machine that installed a Wave 5 package.
"Treat the environment as compromised" and "rotate all credentials accessible from that machine" - Mend Research
- Inventory
package.jsonfiles and lockfiles for Wave 5 package names. Mend's list includes (non-exhaustive):eigenlayer-sdk,graphql-js-client-transform,react-schedule-it,react-remove-properties,mistica-local-rules, multiple@cdktf-constructs/azure-*packages, and multiple@promptions/promptions-*packages. - Hunt for off-registry HTTP dependencies in your dependency graphs. Mend suggests:
grep -r "http://\|https://" package.json package-lock.json | grep -v "registry.npmjs.org\|github.com\|raw.githubusercontent.com" - Block the known C2 indicators at DNS, proxy, and egress:
pack[.]nppacks[.]com,hblnew[.]ecompk[.]com,54[.]160[.]138[.]70, and outbound POSTs topack[.]nppacks[.]com/mozbra.php. - In low-trust install contexts, use
npm install --ignore-scriptsto blockpreinstallhooks. This breaks the chain at Stage 2.
Why this matters for AppSec
The Remote Dynamic Dependency technique is worth understanding. Most registry-scanning tooling inspects the tarball that was published to npm. When the real payload lives on a third-party server and is pulled at install time, that scanning doesn't fire. The published package looks clean.
Combine that with npm's default behaviour of running lifecycle hooks as the installing user - with full access to environment variables, SSH agents, and credential stores - and dependency resolution becomes arbitrary code execution on every machine in your pipeline.
Three practical takeaways:
- Scan for off-registry dependencies, not just known-bad package names. An HTTP URL in a dependency field is a red flag regardless of whether the package name is on any blocklist.
- Run
--ignore-scriptsin CI where you don't need build scripts to execute during install. It's not a complete defence, but it eliminates this entire attack class. - Credentials on developer laptops are pipeline credentials. If your CI token, cloud keys, or SSH agent is accessible from the terminal where you run
npm install, a supply-chain compromise there reaches production.
