Your Seed Phrase Lives in node_modules

Your Seed Phrase Lives in node_modules

By Openlinuxlab | OpenLinuxLab | 8 hours ago


26ff0228fb586d9ba2f6b85fbc7f5326801eed2591e4e6ad757624fea4275f7b.png


# Your Seed Phrase Lives in node_modules

On July 8 a backdoored JavaScript SDK started capturing seed phrases the moment developers generated wallets with it. Four weeks later a self-propagating worm poisoned 444 npm packages in under four hours to harvest credentials from CI pipelines. Both campaigns had the same destination: the private keys sitting on machines that build software. This piece dissects how each attack worked, then walks through the audit that keeps a build machine from ever holding anything worth stealing.

## Goal

You are probably reading this on or near a machine that has run `npm install` recently. That machine may hold, or have held, a mnemonic, a private key, a `.env` with exchange API tokens, or a CI secret that unlocks any of the above. The question we set out to answer is narrow: how do modern supply-chain attacks reach those secrets, and what does a defensible setup look like once you know the answer?

We treated the two July/August incidents as specimens. Same lab bench, same questions for each: entry point, propagation, payload, exit path, and the control that would have broken the chain earliest.

## Specimen one: the SDK backdoor

On July 8, a contributor account with push access to the Injective Labs TypeScript monorepo was compromised. The attacker used it to publish `@injectivelabs/sdk-ts` version 1.20.21 to npm, a package pulling roughly 50,000 weekly downloads. The tampered release stayed live for under an hour before the project team caught it, and eighteen related packages were tainted through dependencies before the dust settled.

The payload was patient. Rather than breaking builds or popping shells, the backdoor hooked the exact functions a crypto developer calls when generating a wallet. When one of those functions ran, the code captured the freshly minted seed phrase and private keys and shipped them off wrapped to look like ordinary analytics telemetry. BleepingComputer and StepSecurity both documented the campaign on July 9, and their reconstructions agree on the essentials.

Three details deserve your attention. First, the capture trigger was semantic: the malware waited for wallet-generation calls instead of harvesting indiscriminately, which keeps its network footprint small enough to blend in. Second, the disguise was boring on purpose — analytics beacons leave every build system constantly, so one more POST request draws no eyes. Third, the compromise vector was an account, not a zero-day: valid credentials beat vulnerabilities, again.

## Specimen two: the worm

Four weeks later the tone changed from scalpel to chainsaw. On August 4, security researchers at StepSecurity tracked a self-propagating worm they later dubbed ChainDrop moving through the npm registry. Starting from a malicious update to `[email protected]`, a widely used key-value utility, it maintained access to maintainer credentials and used them to push infected versions onward. In under four hours it contaminated 444 packages across 2,212 published versions, touching an ecosystem that collectively sees more than 450 million weekly downloads.

Where specimen one hunted wallets directly, this one wanted the plumbing. The dropped payload loaded through Bun into CI environments and harvested whatever credentials the pipeline carried — registry tokens, cloud keys, deploy secrets. Stolen maintainer tokens fed the propagation loop, which is what made it a worm rather than a one-off injection. Exfiltration followed an unusual route: stolen material reached the attackers through Ethereum-based dead-drop addresses, using the blockchain itself as command-and-control infrastructure. The Hacker News covered the campaign the same week, and the registry has since been scrubbed, though scrubbing a cache and scrubbing every clone of a cache are different projects.

## Interpretation: the shared anatomy

Different payloads, identical skeleton. Both attacks entered through trust in the package supply chain rather than through any weakness in cryptography. Both assumed something true about developer machines: they hold secrets, and nobody audits them the way they audit production. And both monetized the same insight — in crypto, the distance between a string of twelve or twenty-four words and full balance drain is one import statement.

There is a broader pattern worth naming here. Coinspect's ongoing "Ill Bloom" research has tallied more than $5 million lost since May to software wallets whose key generation drew from weak random sources. Between compromised packages and weakened randomness, the pattern of 2026 is clear: attackers stopped attacking your cryptography and started attacking the environment your cryptography lives in.

The uncomfortable corollary: if your wallet-generation code runs on the same machine as your build tooling, your threat model has a hole shaped exactly like these two incidents.

## The audit

Here is the checklist we ran on our own machines after digesting both reports. None of it is exotic; all of it closes the specific doors these attacks walked through.

Reproduce installs from the lockfile alone, and skip lifecycle scripts while you are at it. Most supply-chain payloads execute through install scripts, so a machine that never runs them is mostly immune to this entire class:

```bash
npm ci --ignore-scripts
```

Audit what you actually resolved, not what the README promised, and verify registry signatures where npm supports them:

```bash
npm audit --audit-level=high && npm audit signatures
```

Know whether a known-tainted package made it into your tree. The July backdoor lived in one specific version range; checking takes seconds:

```bash
npm ls @injectivelabs/sdk-ts
```

Then the part no command solves. Wallet generation belongs on dedicated, offline-capable hardware, and signing belongs on a hardware wallet that never exports keys in the first place. A build machine with `node_modules` history measured in gigabytes should hold approximately zero secrets — treat any mnemonic that has ever touched it as burned, rotate it, and move the ceremony somewhere that has no telemetry-shaped exits. If your CI needs crypto-adjacent credentials, scope them to a single purpose and expire them fast, because ChainDrop demonstrated that CI caches are now a first-class target.

Separation is the whole game. These campaigns succeeded because development environments are trusted implicitly. Remove the implicit part and both attacks return empty-handed: the SDK backdoor finds no wallet-generation function to hook, the worm finds no standing secrets to lift.

## Limits

Honest boundaries of this analysis. Attribution for both campaigns remains unresolved in public reporting, so nothing above should be read as accusation. Version counts and download figures come from the researchers' snapshots and may be revised as registries finish cleaning up. And `--ignore-scripts` breaks legitimate packages that genuinely need build scripts, so expect to maintain a small allowlist rather than set-and-forget. Finally, signature auditing covers registry-signed metadata only; it would not have caught a compromise of the publishing account itself, which is exactly how specimen one got in. The control that survives every scenario in this piece is physical: keys that never touch a networked build machine cannot be exfiltrated from one.

How do you rate this article?

3


Openlinuxlab
Openlinuxlab

I am a digital nomad traveling through Europe and enjoying topics like tech, hardware, and Linux.


OpenLinuxLab
OpenLinuxLab

Practical, hands-on tutorials for Linux, Termux, Kali and Android security. No copy-pasted commands: every guide is tested on real hardware — phones without root, cheap VPS boxes, fresh installs — and documented with the failures kept in. From Docker and Podman to DNS, SSH hardening and PCAP analysis, everything is written in plain language for beginners and sharp enough for pentesters. Authorized testing only, responsible disclosure always. If you've wasted hours on docs that don't work, you're home.

Publish0x

Send a $0.01 microtip in crypto to the author, and earn yourself as you read!

20% to author / 80% to me.
We pay the tips from our rewards pool.

Page not displaying correctly?