GlassWorm Hijacks Popular React Native Packages — 130K Monthly Downloads Compromised
On March 16, 2026, two legitimate NPM packages were compromised, and in both cases the package.json file was modified and a new pre-install script parameter added. This install script started an install.js script that hadn't been there in earlier versions:

This install.js script was a heavily obfuscated JavaScript loader. After researching the new versions we realized pretty quickly this was a known threat actor.
The GlassWorm threat actor hijacked the two popular React Native packages — react-native-international-phone-number and react-native-country-select — by compromising the maintainer's npm publishing token. The malicious releases were pushed directly to npm with no corresponding GitHub commits, deploying a multi-stage infostealer that uses Solana blockchain transactions as a dead-drop C2 resolver. The attack targets cryptocurrency wallets, npm and GitHub credentials, and browser profile data.
react-native-international-phone-number - Version 0.11.8
This package is a React Native library that helps developers automatically adjust and validate international phone numbers, and is downloaded more than 92,000 times a month.

react-native-country-select - Version 0.3.91
This package is a React Native library that helps developers build mobile apps that understand international calling standards, and is downloaded more than 42,000 times a month.

Compromised packages
Both packages are maintained by @AstrOOnauta. The malicious versions were published on March 16, 2026 at 10:49 and 10:54 UTC respectively — five minutes apart — with no corresponding GitHub releases. The gitHead field in both packages matched the previous clean version, confirming the attacker bypassed the normal development workflow entirely via a stolen npm publishing token.
Importantly, react-native-international-phone-number@0.11.8 depends on react-native-country-select@0.3.9 (the clean version), not the malicious 0.3.91. This confirms both packages were independently compromised rather than cascading through dependencies.
Attack Chain Overview ✓ Verified
1. Attacker publishes malicious versions using stolen npm token 2. npm install triggers preinstall hook: "node install.js" 3. install.js checks for Russian locale/timezone — exits if match (geofencing) 4. Queries Solana wallet 6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ 5. Decodes base64 payload URL from blockchain transaction memo 6. Downloads AES-encrypted stage-2 from 45.32.150.251 or 70.34.242.255 7. Decrypts payload using secretkey + ivbase64 from HTTP headers 8. Executes stage-2 in-memory via eval() or vm.Script — no disk writes 9. Stage-3 downloads Node.js runtime, establishes persistence 10. Kills browsers, harvests 9+ crypto wallets + npm/GitHub credentials 11. Exfiltrates archives to 217.69.3.152/wall
Stage 1: The Loader (install.js)
The malicious install.js file (~19KB, heavily obfuscated) was added to both packages with a new preinstall hook in package.json:
Shared loader hash (SHA-256): 59221aa9623d86c930357dba7e3f54138c7ccbd0daa9c483d766cd8ce1b6ad26
The loader uses RC4-based string encryption with array rotation (javascript-obfuscator toolchain) to hide its functionality.
Russia Geofencing
Before executing any payload, the loader checks whether the system belongs to a Russian-speaking user:
LANG, LANGUAGE, LC_ALLEurope/Moscow, Asia/Krasnoyarsk, Asia/Vladivostok, MSK, and othersIf any check matches, the malware silently exits. This is a well-known pattern in Eastern European and Russian-linked cybercrime operations to avoid targeting domestic users and law enforcement attention.
Solana Blockchain C2 Resolution
Rather than hardcoding a C2 domain that could be taken down, GlassWorm uses the Solana blockchain as a censorship-resistant dead-drop resolver:
6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ ✓getSignaturesForAddress{"link":"base64_url_here"}Verified blockchain data (queried March 17, 2026):
45.32.150.251 (4 different payload paths)70.34.242.255 (1 payload path)This technique allows the attacker to rotate payload servers at any time by simply posting a new Solana memo transaction — without modifying any malware code already deployed in the wild. Taking down one payload server is ineffective as the attacker can redirect to a new one within seconds.
Solana RPC endpoints
All 9 Solana RPC Endpoints (Complete List):
Persistence Lock
The loader writes ~/init.json with a timestamp to prevent re-execution within a 48-hour window.
Stage 2: Encrypted Payload Delivery
The loader sends an HTTP GET request to the payload URL resolved from Solana, with the operating system type sent in the os header (e.g., os: linux, os: win32, os: darwin).
Example verified payload URLs from blockchain:
The response contains a base64-encoded, AES-encrypted stage-2 payload. The decryption key and IV are delivered via HTTP response headers:
Header Example Value
secretkey szfNmayz6fgt6ojbAuVhjEAOWMMxw7iS
ivbase64 ZMM7q5jBwUbsYFo7/8ZdxA==
The decrypted payload is executed entirely in memory:
eval() executionvm.Script sandboxNo stage-2 artifacts are written to disk, making forensic recovery difficult.
Stage 3: The Stealer (Windows-focused)
The stage-3 payload is a comprehensive Windows-focused infostealer.
Persistence
schtasksRun key for startup persistence%APPDATA%\\\\_node_x86 and %APPDATA%\\\\_node_x64Cryptocurrency Wallet Theft
The stealer targets 9+ cryptocurrency wallets via browser extension storage paths:
Browser Extension Wallets:
Desktop Wallet Applications:
The malware kills browser processes (taskkill /F /IM chrome.exe, /IM firefox.exe) to unlock wallet extension files, then harvests:
Developer Credential Theft
Harvests developer credentials that could enable further supply chain attacks:
npm config get # npm registry credentials
git credential fill # GitHub/git credentials
Browser Data Exfiltration
Exfiltration Endpoints
Endpoint Purpose
45.32.150.251 /get_arhive_npm/. Archive exfiltration
217.69.3.152 /wall Wallet data exfiltration
Discovery & Response Timeline
March 13, 2026 Previous clean versions published (0.11.7 and 0.3.9) March 16, 10:49:29 UTC react-native-international-phone-number@0.11.8 published (malicious) March 16, 10:54:18 UTC react-native-country-select@0.3.91 published (malicious) March 16, 11:49 UTC Security issue #165 filed on phone-number repo March 16, 11:55 UTC Security issue #11 filed on country-select repo March 16, 13:15 UTC Maintainer @AstrOOnauta deprecates both compromised versions
Total time from publication to detection: ~1 hour Total time from detectio/n to deprecation: ~1.5 hours
The malicious releases were flagged based on:
preinstall scripts absent in prior versionsinstall.js0.3.91 vs expected 0.3.10)Indicators of Compromise
Malicious Packages
react-native-international-phone-number@0.11.8 react-native-country-select@0.3.91
File Hashes
install.js SHA-256: 59221aa9623d86c930357dba7e3f54138c7ccbd0daa9c483d766cd8ce1b6ad26
Network IOCs ✓ Verified
Primary C2: 45.32.150.251 (Vultr AS20473) Secondary C2: 70.34.242.255 Exfil endpoint: 217.69.3.152 /wall Archive exfil: 45.32.150.251 /get_arhive_npm/ Example payload URLs (from blockchain): - <http://45.32.150[.]251/3e4Tg8V%2F8aCmOJKipASADg%3D%3D> - <http://45.32.150[.]251/IZeqdX38aTS6j3EvNTaC8g%3D%3D> - <http://45.32.150[.]251/8gBwxEq4hvau8hrteHQsEQ%3D%3D> - <http://45.32.150[.]251/R5eXSjHiL85Bb%2B3nKEhl2w%3D%3D> - <http://70.34.242[.]255/htghOzp3JHTwH%2FyM96%2BgUA%3D%3D>
Blockchain IOCs ✓ Verified
Solana wallet: 6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ RPC method: getSignaturesForAddress Transaction count: 5 memos with payload URLs (as of March 17, 2026) Google Calendar: calendar.app.google/2NkrcKKj4T6Dn4uK6
Related Domains
socket[.]network n[.]xyz p[.]link
Filesystem Artifacts
~/init.json (persistence lock with timestamp) %APPDATA%\\\\_node_x86\\\\ (downloaded Node.js runtime) %APPDATA%\\\\_node_x64\\\\ (downloaded Node.js runtime)
Build Environment Fingerprint
Node.js 22.22.0 / npm 10.9.4
Remediation
If you installed either compromised package version:
npm ls react-native-international-phone-number npm ls react-native-country-select
~/init.json on your system%APPDATA%\\\\_node_x86 and %APPDATA%\\\\_node_x64 directories (Windows)npm install react-native-international-phone-number@0.11.7 npm install react-native-country-select@0.3.9
package-lock.json and consider using npm audit as part of your CI/CD pipeline.Conclusion
The GlassWorm React Native attack is a textbook example of why npm token security is critical. A single stolen publishing token gave the attacker the ability to push malicious code to 130,000+ developers per month — with no code review, no PR, and no GitHub trail. The attack's use of Solana blockchain for C2 resolution makes traditional domain takedowns ineffective, and the in-memory execution of encrypted payloads makes forensic detection difficult.
The rapid compromise of these two NPM packages by the GlassWorm threat actor shows they are an active and adaptable operator willing to target multiple ecosystems in rapid succession. Developers should enable npm two-factor authentication, use --ignore-scripts where possible, and monitor for unexpected version publications in their dependency tree.
Verification Methodology
All network IOCs and blockchain data in this post were independently verified on March 17, 2026 by:
https://api.mainnet-beta.solana.com using the getSignaturesForAddress RPC methodThe C2 servers were offline at the time of verification (likely taken down after public disclosure), but the Solana blockchain remains an immutable record of the attack infrastructure.
How can Safety help protect you from these attacks?
Traditional vulnerability scanning happens too late - after potentially malicious code is already in your system. Which means that ASPM and EDR solutions don't protect you from this type of threat.
But all is not lost, as the Safety Firewall protects develoeprs and CI pipelines proactively. Every package installation request is analyzed before reaching public repositories. Malicious, vulnerable, and policy-violating packages are automatically blocked before they can enter your systems, preventing rather than just detecting threats.
You can sign up for a free Safety account and try the Safety Firewall HERE.
Feel free to reach out to me with any questions!