Feed
HighMalicious packagePublished 12 Oct 202624 packages · 24 versions

RubyGems wgkit wave 2 - 24 DeFi/MEV/wallet/NFT crypto gems at `0.9.1` drop a direct `/bin/sh` reverse shell to `45.138.12.177:8089` from `extconf.rb`, same operator as the 2026-10-05 wgkit cluster

Summary

OpenSSF/Amazon Inspector flagged 24 fresh malicious RubyGems on 2026-10-11 (ingested 2026-10-12) - all v0.9.1, all shipping an ext/<name>/extconf.rb base64-decoded Ruby payload that double-forks, sleeps 20-40 min, and pipes a TCP socket to /bin/sh against 45.138.12.177:8089. Same C2 IP, same evasion gates, same bitcoin_rpc_lite_native cover extension as the 2026-10-05 wgkit cluster - this is wave 2 of the same operator, now targeting DeFi/MEV/wallet-HD/NFT/TRC20/jetton verticals.

credential-theftinfostealercrypto-wallet-drainobfuscation
Incident type
Malicious package. A package that was malicious from its first publish under its own name - a fake tool, a lure used in a social-engineering campaign, or a trojanised utility - rather than a copy of an existing name.
Detected by
OpenSSF malicious-packages · Amazon Inspector · GitHub Advisory Database
Also known as
wgkit RubyGems crypto wave 2 · 45.138.12.177:8089 RubyGems DeFi reverse-shell burst · bitcoin_rpc_lite_native extconf.rb RubyGems wave 2
Ecosystems
RubyGems
Packages tracked
24

What happened

Between 2026-10-10 11:42 UTC (the OSSF malicious-packages cutoff of yesterdays sweep) and 2026-10-12 06:11 UTC (todays ingest-window start), the GitHub Advisory Database and OpenSSF malicious-packages published 24 fresh RubyGems malware advisories, every one of them pointing at the same C2 and sharing the operator fingerprint of the 2026-10-05 wgkit crypto cluster.

Operator continuity vs. the 2026-10-05 wave

Signal2026-10-05 wgkit wave 1 (25 gems)2026-10-11 wgkit wave 2 (24 gems - this file)
C2 subnet45.138.0.0/16 (.12.177, .17.70, .17.177, .122.177, .127.77, .172.177)45.138.12.177:8089 (one of the wave-1 endpoints)
Payload deliveryBase64/XOR fetch of wgkit.tar.gz -> /tmp/.w1/wg_install.sh second stageDirect /bin/sh reverse shell via TCP socket pipe to C2
Package version1.0.0 across all 250.9.1 across all 24
Native-ext fileext/<name>/extconf.rb with base64 payloadext/<name>/extconf.rb with base64 payload (same technique)
Native-ext namebitcoin_rpc_lite_native on multiple slugsbitcoin_rpc_lite_native on every slug
Evasion gatesCI env + path prefix + hostname regex + developer-artefact presence + uptime > 1800 s + 20-40 min jitterIdentical set
VerticalEthereum / Bitcoin / Lightning / BIP32-BIP39 / TRON basicsDeFi / MEV / airdrop / NFT / stablecoin / cross-chain (the un-covered half of the Web3 attack surface)
Disclosure pathOSSF Amazon Inspector -> malicious-packages -> GHSAOSSF Amazon Inspector -> malicious-packages -> GHSA

The shared C2 IP (45.138.12.177:8089 is one of the wave-1 ports verbatim), the shared native-extension cover name across unrelated slugs, the shared evasion-gate list, and the shared verbatim OSV submission template argue for one operator shipping a second production wave against the un-covered half of the Web3 vertical.

Package inventory (all v0.9.1, all pointing at 45.138.12.177:8089)

PackageGHSAOSV/MAL
airdrop-eligibility-checkGHSA-qmg2-cxmc-2xm5MAL-2026-17779
block-explorer-apiGHSA-hg3j-6p9h-76jmMAL-2026-17780
btc-fee-estimatorGHSA-4264-cr8p-9wh7MAL-2026-17781
crypto-tax-exportGHSA-7qmm-9mrq-vf4qMAL-2026-17782
defi-yield-calculatorGHSA-qchc-hrjm-3rwvMAL-2026-17783
dex-router-abisGHSA-j34r-6fqr-vh5pMAL-2026-17784
erc20-approve-auditGHSA-mq54-cvw7-j5m5MAL-2026-17785
eth-gas-oracleGHSA-3h65-764h-38ggMAL-2026-17786
evm-tx-decoderGHSA-9f63-cxjq-v6f8MAL-2026-17787
gas-refuel-bridgeGHSA-vpf2-wcf3-pq8jMAL-2026-17788
hd-wallet-generatorGHSA-539m-69r6-rw3mMAL-2026-17789
mev-sandwich-detectGHSA-pcpf-mq97-v8ppMAL-2026-17790
multichain-rpcGHSA-hh53-qgqp-j52vMAL-2026-17791
nft-metadata-resolverGHSA-9f8r-f7cw-6pv8MAL-2026-17792
perp-funding-ratesGHSA-rpp6-g37v-xmghMAL-2026-17793
seed-phrase-validatorGHSA-vfwp-3q5f-qqrhMAL-2026-17794
sol-mint-utilsGHSA-3xwh-c3gj-3f29MAL-2026-17795
staking-apr-fetcherGHSA-5wxm-jv9m-mw2rMAL-2026-17796
ton-jetton-toolsGHSA-xqg7-h4h5-x6pfMAL-2026-17797
tron-trc20-utilsGHSA-94vm-385v-mjfjMAL-2026-17798
wallet-balance-scannerGHSA-g92c-g6pm-wf38MAL-2026-17799
wallet-hd-deriveGHSA-9grv-7vv7-5ppjMAL-2026-17800
web3-signer-kitGHSA-m6qx-67h3-wwrhMAL-2026-17801
xrp-ledger-utilsGHSA-p4hf-p5fc-85p7MAL-2026-17802

Classification: malicious-package (24 fresh brand-adjacent lures published for this wave; none hijacks a legitimate upstream, so this is not a compromise). Severity: high - confirmed install-time RCE and persistent interactive shell on developer workstations with crypto credentials, but reach is limited to developers who gem install a lure, exactly matching the wave-1 severity call.

Discovery

OpenSSF malicious-packages (ingested via Amazon Inspector`s IN-MAL feed), published to GitHub Advisory Database on 2026-10-11.

Affected packages (24)

These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once - it runs in your browser and nothing is uploaded.

Impact

  • One operator - continuation of the 2026-10-05 "wgkit" RubyGems crypto cluster. Every one of todays 24 gems shares with the earlier 25-gem wave: (a) C2 at 45.138.12.177:8089 on the same 45.138.0.0/16 superblock, (b) the bitcoin-rpc-lite README cover text and bitcoin_rpc_lite_native native-extension name across unrelated package slugs, (c) the identical evasion gating list (~/.ssh, ~/.gitconfig, ~/.npmrc, ~/.gem/credentials, ~/.bundle presence; uptime > 1800 s; CI / GITHUB_ACTIONS / TRAVIS / JENKINS / GITLAB_CI / CODESPACES env skips; uvm/firecracker/sandbox/vagrant hostname skips; /opt/rubygems//tmp//var/tmp//workspace path skips), (d) the 20-40 minute jittered sleep inside a double-forked setsid detached child, (e) the Amazon Inspector-first disclosure path with OSSF malicious-packages` MAL-2026-177XX IDs
  • Payload family shift from wave 1: the 2026-10-05 wave fetched wgkit.tar.gz from the 45.138.*.* subnet and ran /tmp/.w1/wg_install.sh as a staged second-stage installer; todays wave 2 skips the staged dropper and goes straight to **TCP socket piped to /bin/sh** in an infinite reconnect loop. On every single wave-2 gem the sink is 45.138.12.177:8089, exactly matching the port reused on bitcoin-rpc-lite and web3-eth-utils` in wave 1
  • Target vertical shift from wave 1: wave 1s 25 gems were Ethereum / Bitcoin / Lightning Network / BIP39 / BIP32 / TRON basics (eth-keystore-utils, btc-wallet-tools, keccak typos, ethereum.rb typos, tron-rb). Wave 2s 24 gems cover the DeFi / MEV / airdrop / NFT / stablecoin / cross-chain space that the first wave did not: Solana (sol-mint-utils), XRP Ledger (xrp-ledger-utils), TRON TRC-20 (tron-trc20-utils), TON jettons (ton-jetton-tools), MEV sandwich detection (mev-sandwich-detect), DEX router ABIs (dex-router-abis), perp funding rates (perp-funding-rates), airdrop eligibility (airdrop-eligibility-check), ERC-20 approvals auditing (erc20-approve-audit), gas estimation (btc-fee-estimator, eth-gas-oracle), tax export (crypto-tax-export), yield (defi-yield-calculator), bridges (gas-refuel-bridge), NFT metadata (nft-metadata-resolver), block explorers (block-explorer-api), multi-chain RPC (multichain-rpc), EVM tx decoding (evm-tx-decoder), staking APR (staking-apr-fetcher), balance scanning (wallet-balance-scanner), HD derivation (hd-wallet-generator, wallet-hd-derive), seed phrase validation (seed-phrase-validator), Web3 signing (web3-signer-kit). None of the 24 names is a strict single-char typosquat; all are brand-adjacent lures manufactured fresh for the wave to look like plausible utility gems a DeFi/Web3 Rubyist would try first
  • Target victim profile remains "developer workstation with crypto credentials": the same six developer-signal files (~/.ssh, ~/.gitconfig, ~/.npmrc, ~/.gem/credentials, ~/.bundle, ~/.ethereum/keystore) must be present for the payload to fire, and the shell is /bin/sh with the installer users privileges. On any hit, treat SSH private keys, GitHub/GitLab/Codeberg PATs, RubyGems API key (~/.gem/credentials), npm authToken (~/.npmrc), Bundler config (~/.bundle/config), any ~/.ethereum/keystore/` and the seed phrases those encrypt*, hardware-wallet companion secrets, DeFi exchange CLI credentials, MetaMask browser-profile data, Phantom and Solana wallet state, hot wallets of ANY chain accessible from the user profile, and - if the installer user was privileged - ~/.aws/credentials and ~/.config/gcloud as fully compromised
  • Install-time native-extension abuse mechanism (unchanged from wave 1): every gem declares ext/<name>/extconf.rb in its gemspecs require_paths with a native-extension name of bitcoin_rpc_lite_native (independent of the slug - a hint that the operator ships one wave-2 payload template and only rebrands the gemspec summary, description, and homepage). gem install auto-runs extconf.rb to generate a Makefile. Here the extconf.rb IS the payload: it base64-decodes an embedded Ruby string with Base64.decode64 and runs it under eval from inside a double-fork setsid detached child. There is no shipped C source and no real native extension to build. The gems lib/<name>.rb is a two-method stub (build_id = "ok", healthy? = true) that lets require succeed if a confused developer actually tries to use it, and the README text copy-pastes bitcoin-rpc-lite tagline across every slug regardless of the actual gem name

What to do

  1. 1grep -nE "(wallet-balance-scanner|xrp-ledger-utils|staking-apr-fetcher|wallet-hd-derive|web3-signer-kit|tron-trc20-utils|ton-jetton-tools|crypto-tax-export|gas-refuel-bridge|btc-fee-estimator|evm-tx-decoder|hd-wallet-generator|sol-mint-utils|defi-yield-calculator|block-explorer-api|perp-funding-rates|airdrop-eligibility-check|erc20-approve-audit|nft-metadata-resolver|eth-gas-oracle|dex-router-abis|mev-sandwich-detect|multichain-rpc|seed-phrase-validator)" Gemfile Gemfile.lock *.gemspec across every Rails/Sinatra/Jekyll/crypto-tooling repo. On any hit: gem uninstall <name>, delete Gemfile.lock, invalidate any Docker image layer that ran bundle install after 2026-10-11, rebuild from scratch
  2. 2Host-level hunt on any workstation or CI runner that ran gem install or bundle install against any of the 24 slugs since 2026-10-11: audit outbound connections to 45.138.12.177:8089, orphan long-lived ruby processes in session leader state (ps -eo pid,ppid,sid,user,command | grep -i ruby | grep -v grep - the double-forked payload is a session leader detached from any shell), suspicious /bin/sh descendants of a ruby parent, and extconf.rb under ~/.gem/ruby/*/gems/<name>-0.9.1/ext/. Any single hit means image the host - the shell is interactive and the operator can have dropped anything the installer user could reach
  3. 3Rotate on any confirmed hit (and on strong suspicion): SSH keys (~/.ssh/*), Git tokens (~/.gitconfig, ~/.config/gh, ~/.config/glab, GitHub/GitLab PATs), RubyGems API key (log in to rubygems.org, revoke old key, issue new one), npm authToken (~/.npmrc), Bundler config (~/.bundle/config), any ~/.ethereum/keystore/* (treat the seed phrases these encrypt as exposed - rotate the wallets to fresh seeds, not just the config), MetaMask and Phantom browser profiles, hardware-wallet companion-app secrets, exchange CLI credentials. On a developer who runs gem install as a privileged user, assume ~/.aws/credentials, ~/.config/gcloud, and any kubectl kubeconfig under ~/.kube/ are reachable - rotate those too
  4. 4Egress blocklist additions for CI, build hosts, and corporate developer egress proxies: deny outbound TCP to 45.138.12.177:8089 immediately. Extend to the full 45.138.0.0/16 superblock if your proxy supports it (keeps the standing wave-1 denylist of 45.138.12.0/24, 45.138.17.0/24, 45.138.122.0/24, 45.138.127.0/24, 45.138.172.0/24 in force). Deny outbound plain HTTP from CI by default; whitelist specific HTTPS mirrors instead
  5. 5Developer education: there are no mainstream Ruby gems for DEX router ABIs, MEV sandwich detection, perp funding rates, airdrop eligibility, TON jettons, TRC-20 operations, EVM tx decoding, or multichain RPC - the Ruby ecosystem has ethereum.rb and that is largely it. Any gem that advertises Web3/DeFi/NFT functionality at 0.9.1 with no release history, an ext/<name>/extconf.rb whose native-extension name is bitcoin_rpc_lite_native across unrelated packages, and a lib/<name>.rb that only exports build_id and healthy? methods is a tarball-inspection-in-a-sandbox job before any gem install or any bundle install

References

rubygems-2026-10-12-wgkit-wave-2-crypto-defi-cluster