Skip to main content

RubyGems Cryptojacking: Trojanized Gems

Published 9 min read

RubyGems cryptojacking cover: trojanized gem packages feeding an XMRig Monero miner, with SSH and cross-language worm arrows, and stat tiles reading 113 gems, 14,253 downloads, and 2 actors.

TL;DR — Unit 42 (Palo Alto Networks) reported two threat actors flooding RubyGems with trojanized copies of popular Ruby libraries carrying XMRig Monero miners. Actor "Prvaz12_mars" published 113 gems on 13 July 2026 (14,253 downloads) with a worming, persistence-heavy, triple-encrypted payload; actor "monib110" published 23 gems by 16 July with a simpler inline miner. A third account, "Andrey78," sat clean with 309 gems and 139,514 downloads — a probable staging account. This is supply-chain cryptojacking that also spreads across languages and SSH.

About this analysis. This is a PhishEye Threat Research summary of findings published by Unit 42 (Palo Alto Networks) on 22 July 2026. All indicators are attributed to Unit 42 and defanged. PhishEye did not independently discover or investigate this campaign; our contribution is defensive context for the teams that consume open-source Ruby packages.

What Unit 42 documented

According to Unit 42, two RubyGems accounts weaponized the open-source Ruby ecosystem to mine Monero at scale. The pattern is familiar from other package-registry campaigns — take the name and code of a legitimate, popular library, inject a payload into the entry point, and publish under plausible-sounding names — but the two operators here differ sharply in sophistication. Unit 42's researchers documented both, plus a related account that stayed dormant.

The shared naming convention is the tell. Both actors drew package names from a fixed adjective-noun grammar: a size prefix ({giga, nano, ultra, hyper, piko, super, mega, micro, mini, tiny}), a quality word ({pure, sharp, smart, pro, safe, clean, fast, quick, lite, max}), and a package-type suffix ({kit, tool, mod, pkg, hub, lib, box, rb, sys, gem}). The result — ultra-smart-tool, nano-sharp-kit, giga-clean-box — reads as generic tooling and blends into search results.

Actor 1: Prvaz12_mars

Unit 42 reported that Prvaz12_mars (jdvrie98@gmail[.]com) published 113 malicious gems on 13 July 2026, together reaching 14,253 downloads. Each gem is a trojanized copy of a genuine, popular Ruby library, with an identical XMRig cryptojacking payload injected into the bundled library's entry-point file — so the package still does what a victim expects while mining in the background.

The payload is built to survive and to hide. Per Unit 42, it uses a five-hour delayed trigger — Thread.new{sleep 18000; ...} — so nothing malicious fires during the short window a sandbox typically observes. Before mining, it performs anti-analysis checks: detecting virtual machines (VMware, VirtualBox, QEMU), containers (/.dockerenv, cgroup markers), and debuggers, and declining to run if any are present.

Persistence is layered across three independent mechanisms: appending to ~/.bashrc, installing a crontab entry, and creating a systemd user service. That redundancy means removing one foothold leaves two behind.

Two behaviors push this beyond ordinary cryptojacking. First, SSH lateral movement: the payload reads ~/.ssh/id_rsa and ~/.ssh/known_hosts, then propagates to the known hosts it finds — turning one infected developer workstation into a launch point against every server that developer can reach. Second, a cross-language worm: it infects local Node.js projects (via package.json postinstall), Python (setup.py), Ruby (.gemspec), Docker (Dockerfile), git (pre-commit hooks), and VSCode extensions. A RubyGems infection therefore does not stay in the Ruby ecosystem — it seeds itself into whatever other build systems live on the same machine.

The miner itself is tuned to stay quiet. Unit 42 noted load-aware mining that pauses when system load is high, with the XMRig max-threads-hint capped at 50 percent, keeping CPU usage below the level that would prompt a developer to investigate. The configuration is protected with triple-layer encryption (AES-256-GCM, RSA-4096, and ChaCha20). All 113 gems mine to a single Monero wallet across four pools: moneroocean, p2pool, supportxmr, and herominers.

Actor 2: monib110

The second operator, monib110 (nsrtytyam687@gmail[.]com), ran a slower, cruder operation. Unit 42 reported that this actor first published clean placeholder gems on 12 July — same adjective-noun naming, with the description "University research based on..." — then weaponized all 23 packages on 16 July by introducing a simplified XMRig payload. The staged approach (publish benign, weaponize later) is worth noting on its own: a package that scanned clean at install time is not guaranteed to stay clean.

The payload lives in a hidden file, lib/.threadpool.rb, loaded via require_relative '.threadpool' from the main entry point. Unlike Actor 1, there is no obfuscation (plaintext Ruby with an XMRigLauncher module), and it fetches XMRig dynamically through the GitHub API (api.github[.]com/repos/xmrig/xmrig/releases/latest), then runs the miner inline via exec(). There is no persistence, no worm, and no anti-analysis. It mines to a single pool, pool.supportxmr[.]com:3333.

monib110 also used two naming strategies. The first reuses the adjective-noun pattern shared with Prvaz12_mars. The second is typosquatting through character substitution — i to 1, o to 0, doubled letters — against real, high-traffic gems. Unit 42 listed the typosquat targets: minitest, rake, activesupport, addressable, json, aws-partitions, aws-sdk-core, aws-sigv4, jmespath, i18n, aws-eventstream, rack, tzinfo, faraday, public_suffix, rspec-core, http-cookie, multipart-post, and bundler. Names like minitestt, js0n, bundelr, and tz1nfo catch fat-finger installs and copy-paste errors.

Unit 42 also flagged Andrey78 (cakoc614@gmail[.]com): 309 gems and 139,514 total downloads, published 5–14 July and still live on RubyGems, with no malicious content detected as of 15 July. Unit 42 assessed it as likely a staging or test account for the campaign. The download count is far larger than either weaponized account's, which is the uncomfortable part — a large, trusted-looking package footprint is exactly what a later weaponization step would want, and clean-today is not a guarantee of clean-tomorrow.

Why this matters for defenders

The through-line across both actors is that the registry is the delivery channel and the developer machine is the target. Two properties make this campaign more dangerous than commodity cryptojacking. The SSH propagation converts a single careless gem install into potential movement across a fleet. And the cross-language worming means Ruby-specific defenses are insufficient — the infection reaches Node, Python, Docker, and git tooling on the same host. Add the five-hour delay and VM/container/debugger evasion, and install-time scanning in a sandbox can plausibly return a clean verdict on a package that is designed to do nothing until it is somewhere real.

What defenders should do

  • Pin and lock dependencies. Commit Gemfile.lock and install with bundle install --frozen (or --deployment) so an unreviewed name can never resolve into a build. Do the same across ecosystems with lockfiles.
  • Scrutinize package names against the documented grammar. Treat size-quality-type names (ultra-smart-tool, giga-clean-box) and character-substitution typosquats (minitestt, js0n, tz1nfo, bundelr) as suspect until proven legitimate; verify you are installing the exact upstream name.
  • Do not run gem install or bundle install for untrusted packages on a workstation that holds SSH keys. Use disposable, network-restricted build containers, and prefer allowlisted internal mirrors over the public registry.
  • Hunt for the persistence artifacts on developer and CI hosts: new crontab entries, unexpected systemd user services, and appended lines in ~/.bashrc, plus any lib/.threadpool.rb in installed gems.
  • Monitor for the behavioral signatures rather than only file hashes: outbound connections to XMRig mining pools, unexpected reads of ~/.ssh/id_rsa and ~/.ssh/known_hosts, and pulls of XMRig release artifacts from GitHub.
  • Watch for cross-ecosystem tampering: injected postinstall scripts in package.json, modified setup.py, altered .gemspec files, new git pre-commit hooks, and unexpected VSCode extension changes.
  • Rotate any SSH keys that were present on a host you suspect touched these gems, and review known_hosts reachability as a lateral-movement blast radius.
  • Treat clean-at-install as temporary: a package can be benign at publish and weaponized later (monib110's Jul 12 to Jul 16 pattern; Andrey78's dormant footprint). Re-scan dependencies over time, not only at first install.

Indicators (attributed to Unit 42, defanged)

Defanged; re-fang by replacing [.] with . These are live or known-malicious; handle in isolation.

# Prvaz12_mars: Monero wallet
47vT2mcSzKPP2fEnZJ5QaVaF2fEEmvhxZHi26Hn9XixhY6tqNTtpXE8XXhG7Uoj6eta9a9HWmhssuS712s271jFf5vPngnn

# Prvaz12_mars: mining pools
pool.moneroocean[.]stream:443
p2pool[.]io:443
pool.supportxmr[.]com:443
de.monero.herominers[.]com:443

# Prvaz12_mars: XMRig download URLs
raw.githubusercontent[.]com/xmrig/xmrig/v6.22.2/xmrig-6.22.2-linux-static-x64.tar.gz
raw.githubusercontent[.]com/xmrig/xmrig/v6.22.2/scripts/setup.sh
github[.]com/xmrig/xmrig/releases/download/v6.22.2/xmrig-6.22.2-linux-static-x64.tar.gz

# Prvaz12_mars: account
jdvrie98@gmail[.]com
rubygems[.]org/profiles/Prvaz12_mars
# monib110: Monero wallet
8Aao1ANqXNeAfreezPgN3HYm5o96Jo8qEACDBZ1aZjjp5sRoP8HGcJwF97GEfP5GXofm9Y5vRMsWrWpxNNmKcQWh9qnqXZ2

# monib110: mining pool + XMRig fetch
pool.supportxmr[.]com:3333
api.github[.]com/repos/xmrig/xmrig/releases/latest

# monib110: account
nsrtytyam687@gmail[.]com
rubygems[.]org/profiles/monib110
# Related / staging account (no malicious content detected as of Jul 15)
cakoc614@gmail[.]com
rubygems[.]org/profiles/Andrey78
# Malicious gems: representative sample (Prvaz12_mars, 113 total)
rubygems[.]org/gems/ultra-smart-tool
rubygems[.]org/gems/nano-sharp-kit
rubygems[.]org/gems/ultra-pro-pkg
rubygems[.]org/gems/hyper-safe-hub
rubygems[.]org/gems/giga-clean-kit
rubygems[.]org/gems/mega-pro-kit
rubygems[.]org/gems/super-lite-hub
rubygems[.]org/gems/micro-fast-mod
rubygems[.]org/gems/piko-clean-hub
rubygems[.]org/gems/giga-max-kit

# Malicious gems: representative sample (monib110, 23 total, incl. typosquats)
rubygems[.]org/gems/minitestt
rubygems[.]org/gems/rakee
rubygems[.]org/gems/activesuport
rubygems[.]org/gems/addresable
rubygems[.]org/gems/js0n
rubygems[.]org/gems/bundelr
rubygems[.]org/gems/aws-sdk-c0re
rubygems[.]org/gems/tz1nfo
rubygems[.]org/gems/faradayy
rubygems[.]org/gems/public_suff1x

Totals per Unit 42: Prvaz12_mars, 113 gems (14,253 downloads); monib110, 23 gems; Andrey78 (staging), 309 gems (139,514 downloads). The full package lists are available in Unit 42's source material.

Sources

FAQ

What is this RubyGems campaign? Per Unit 42, two threat actors published trojanized copies of popular Ruby libraries to RubyGems, each carrying an XMRig Monero-mining payload — supply-chain cryptojacking that hides inside otherwise-working packages.

How many packages and downloads were involved? Unit 42 reported 113 malicious gems from Prvaz12_mars (14,253 downloads) and 23 from monib110. A related account, Andrey78, held 309 clean gems with 139,514 downloads and is assessed as a likely staging account.

How do the two actors' payloads differ? Prvaz12_mars used a sophisticated payload with a five-hour delay, anti-analysis evasion, triple-layer encryption, three persistence mechanisms, SSH lateral movement, and cross-language worming. monib110 used a simple plaintext inline miner with no persistence, worm, or evasion.

How can I tell if a gem is part of this campaign? Watch for the adjective-noun-type naming grammar (e.g. ultra-smart-tool, giga-clean-box) and character-substitution typosquats of real gems (e.g. minitestt, js0n, tz1nfo, bundelr). Confirm you are installing the exact, legitimate upstream package name.

What should I do if I may have installed one? Isolate the host, check for the persistence artifacts (crontab, systemd user service, ~/.bashrc additions, lib/.threadpool.rb), look for outbound mining-pool traffic and reads of your SSH keys, rotate any SSH keys that were present, and scan other ecosystems (Node, Python, Docker, git) on the same machine.


About the authors

PhishEye Threat Research analyzes emerging phishing and digital-risk campaigns for defenders. This article summarizes and adds defensive context to research originally published by Unit 42 (Palo Alto Networks) — authored by Moe Ghasemisharif, Ruian Duan, Zhanhao Chen, and Daiping Liu — with all indicators attributed to them. PhishEye did not independently discover or investigate this campaign.