Armando identified ethers-providerz v1.18.0 as the final version in a three-version malicious npm package cluster published on March 13, 2025. The package impersonates the legitimate ssh2 library and installs a downloader that fetches a second-stage Node.js payload from a remote C2 server, consistent with a reverse shell campaign also observed in the related package ethers-provider2. All 178 downloads of ethers-providerz occurred before npm removed it from the registry.
Key Findings
- Malicious version: v1.18.0, published 2025-03-13; no clean predecessor exists -- all three versions of this package are malicious
- Entry point: install lifecycle hook fires automatically on npm install
- Targets: Node.js developer machines and CI/CD pipelines -- executes a remotely fetched Node.js payload
- Evasion: C2 URL encoded with two layers of base64 (atob applied twice); temp file deleted after execution to reduce disk artifacts
- Detection: Script-JS.Downloader.SupplyChain, Text.Downloader.SupplyChain
Package Background
ethers-providerz claims to be "SSH2 client and server modules written in pure JavaScript for node.js," pointing to github.com/mscdex/ssh2 as its homepage. This directly impersonates the real ssh2 npm package maintained by Brian White. The package was first published on March 13, 2025, and version 1.18.0 was uploaded at 16:38 UTC -- about 77 minutes after the first version. All three versions are malicious and contact the same C2 server, confirming a coordinated campaign. The package was removed from npm and has zero direct dependents in the registry, but 178 total downloads suggest developers were exposed.
Attack Analysis
Like versions 1.16.0 and 1.17.0, ethers-providerz v1.18.0 declares an install lifecycle hook in package.json that points to install.js. Node.js executes this script automatically during npm install, before the installing project's own code runs.
The install script opens with a node-gyp rebuild call that mimics the native binding build step from the legitimate ssh2 package -- camouflage designed to make the script appear routine to a quick visual review. Immediately after, a self-invoking anonymous function calls twice on the string . The first decode yields another base64 string; the second yields the plaintext C2 URL .