.png)
Active Supply Chain Attack: Malicious node-ipc Versions Published to npm
StepSecurity's AI Package Analyst detected three malicious node-ipc versions (9.1.6, 9.2.3, 12.0.1) published simultaneously on May 14, 2026 by a rogue/compromised maintainer account, injecting an 80KB obfuscated IIFE into the CommonJS bundle that harvests 90+ credential file categories (AWS, Azure, GCP, SSH, Kubernetes, GitHub, Claude AI/Kiro configs, Terraform, etc.) and exfiltrates them via HTTPS and raw DNS TXT queries to a typosquatted Azure-mimicking C2 domain. The writeup includes a full stage-by-stage technical teardown (daemonization, SHA-256 targeting gate on 12.0.1, custom base-16 nibble-reversed obfuscation, dual-channel exfiltration) plus file hashes, network IOCs, and remediation guidance for developers and CI/CD pipelines.
What it is
Malicious npm versions node-ipc@9.1.6, 9.2.3, and 12.0.1, published May 14, 2026 by maintainer account atiertant (a.tiertant@atlantis-software.net), which had no prior publish history on the package — a 21-month gap since the last legitimate release (12.0.0, Aug 12, 2024). npm's latest dist-tag currently points to the compromised 12.0.1.
How it works
The payload is an 80,079-byte obfuscated IIFE appended after module.exports in node-ipc.cjs (line 1271). It fires unconditionally on any require('node-ipc') — no install-hook, no lifecycle script, so tools that only scan preinstall/postinstall are blind to it. The ESM bundle and source files are untouched, so projects importing via import with bundlers resolving the "module" field are unaffected; only require()/"main" resolution is at risk.
Only 12.0.1 has a targeting gate: it computes SHA256(path.normalize(module.filename).toLowerCase()) and compares it against a hardcoded hash (bf9d8c0c3ed3ceaa831a13de27f1b1c7c7b7f01d2db4103bfdba4191940b0301), silently exiting on non-matching machines. This hash cannot be reversed to identify the target without brute force. The 9.x versions carry no gate and run on every install — notably, the legitimate 9.x line never shipped a .cjs bundle at all, so those releases are entirely fabricated packages sharing only a name with real 9.x history.
On a match (or unconditionally for 9.x), the process daemonizes via child_process.fork with env marker __ntw=1, strips NODE_OPTIONS, and detaches with stdio: 'ignore'. The daemon stages data in $TMPDIR/nt-<PID>/, builds a TAR+gzip archive of harvested files, and exfiltrates over two parallel channels to sh.azurestaticprovider.net (resolved IP 37.16.75.69): HTTPS POST with HMAC-SHA256-signed chunks, and raw DNS TXT queries sent directly to the C2 IP (bypassing public resolvers, so corporate DNS logging won't see it).
Preconditions / Affected
- Any dependency resolving to node-ipc 9.1.6, 9.2.3, or 12.0.1 — direct, transitive, or via unpinned install.
- Only code paths using
require()/CommonJS resolution are hit; pure ESM imports are not. - For 12.0.1, exploitation additionally requires the module's file path to match the attacker's precomputed target hash — otherwise it's inert.
What to do
npm ls node-ipc
npm ls node-ipc --all 2>/dev/null | grep -E '9\.1\.6|9\.2\.3|12\.0\.1'
grep -E '"node-ipc".*"(9\.1\.6|9\.2\.3|12\.0\.1)"' package-lock.json
grep -E 'node-ipc@(9\.1\.6|9\.2\.3|12\.0\.1)' yarn.lockPin to last known-clean releases and regenerate the lockfile:
npm install node-ipc@9.2.1 # for 9.x users
npm install node-ipc@12.0.0 # for 12.x usersCheck for daemon artifacts:
ls -la "${TMPDIR}/nt-"* 2>/dev/null || ls -la /tmp/nt-* 2>/dev/null
grep -rl '__ntw' /proc/*/environ 2>/dev/null # Linux
ps auxeww | grep __ntw # macOSIf any compromised version was installed anywhere (dev machine or CI), treat all secrets in that environment as compromised — rotate immediately, in priority order: AWS IAM keys, SSH keys (revoke from authorized_keys), Kubernetes service account tokens, GitHub tokens/OAuth apps, Azure/GCP/OCI service account keys, .env secrets, Claude AI/Anthropic API keys, DB passwords (.pgpass, .my.cnf), npm publish tokens (.npmrc). For CI/CD, rotate all injected secrets including GITHUB_TOKEN and deploy/OIDC credentials, and audit cloud audit logs (CloudTrail, Azure Activity Log, GCP Audit Log) for the compromised window.
Caveats
The targeting hash on 12.0.1 is a one-way SHA-256 — the page states explicitly there is no way to determine which specific machine/path was targeted without brute-forcing the input space, so exposure for 12.0.1 installs outside the target can't be confirmed or ruled out from the hash alone.
Organisations named here
- Brandon Nozaki Miller
- peacenotwar
- sh.azurestaticprovider.net
Technologies named here
- node-ipc
- StepSecurity AI Package Analyst
- StepSecurity Threat Center
- Harden-Runner
- StepSecurity Secure Registry
- StepSecurity Dev Machine Guard
- npm Package Cooldown Check
- NPM Package Compromised Updates Check
- npm Package Search
- npm
- Node.js
- StepSecurity
Techniques named here
- Multi-version blast-radius maximization
- Fabricated package versions
- Payload injection into CommonJS bundle
- Lifecycle-hook scan evasion
- ESM/CommonJS selective compromise
- setImmediate deferral to avoid blocking event loop
- Custom base-16 encoding with reversed nibble order
- String array shuffling
- Control flow flattening
- Dead code injection
- SHA-256 targeting gate
- Process daemonization / detached child process
- Character-by-character command construction
- Bulk credential harvesting via file pattern matching
- Archive staging and compression for exfiltration
- Dual-channel exfiltration
- Domain typosquatting mimicking Azure infrastructure
- DNS resolver override for covert exfiltration
- DNS TXT record data exfiltration
Threat actors named here
- atiertant
- RIAEvangelist
- peacenotwar incident
Related in Supply Chain


