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
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.
- 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
| Signal | 2026-10-05 wgkit wave 1 (25 gems) | 2026-10-11 wgkit wave 2 (24 gems - this file) |
|---|---|---|
| C2 subnet | 45.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 delivery | Base64/XOR fetch of wgkit.tar.gz -> /tmp/.w1/wg_install.sh second stage | Direct /bin/sh reverse shell via TCP socket pipe to C2 |
| Package version | 1.0.0 across all 25 | 0.9.1 across all 24 |
| Native-ext file | ext/<name>/extconf.rb with base64 payload | ext/<name>/extconf.rb with base64 payload (same technique) |
| Native-ext name | bitcoin_rpc_lite_native on multiple slugs | bitcoin_rpc_lite_native on every slug |
| Evasion gates | CI env + path prefix + hostname regex + developer-artefact presence + uptime > 1800 s + 20-40 min jitter | Identical set |
| Vertical | Ethereum / Bitcoin / Lightning / BIP32-BIP39 / TRON basics | DeFi / MEV / airdrop / NFT / stablecoin / cross-chain (the un-covered half of the Web3 attack surface) |
| Disclosure path | OSSF Amazon Inspector -> malicious-packages -> GHSA | OSSF 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)
| Package | GHSA | OSV/MAL |
|---|---|---|
airdrop-eligibility-check | GHSA-qmg2-cxmc-2xm5 | MAL-2026-17779 |
block-explorer-api | GHSA-hg3j-6p9h-76jm | MAL-2026-17780 |
btc-fee-estimator | GHSA-4264-cr8p-9wh7 | MAL-2026-17781 |
crypto-tax-export | GHSA-7qmm-9mrq-vf4q | MAL-2026-17782 |
defi-yield-calculator | GHSA-qchc-hrjm-3rwv | MAL-2026-17783 |
dex-router-abis | GHSA-j34r-6fqr-vh5p | MAL-2026-17784 |
erc20-approve-audit | GHSA-mq54-cvw7-j5m5 | MAL-2026-17785 |
eth-gas-oracle | GHSA-3h65-764h-38gg | MAL-2026-17786 |
evm-tx-decoder | GHSA-9f63-cxjq-v6f8 | MAL-2026-17787 |
gas-refuel-bridge | GHSA-vpf2-wcf3-pq8j | MAL-2026-17788 |
hd-wallet-generator | GHSA-539m-69r6-rw3m | MAL-2026-17789 |
mev-sandwich-detect | GHSA-pcpf-mq97-v8pp | MAL-2026-17790 |
multichain-rpc | GHSA-hh53-qgqp-j52v | MAL-2026-17791 |
nft-metadata-resolver | GHSA-9f8r-f7cw-6pv8 | MAL-2026-17792 |
perp-funding-rates | GHSA-rpp6-g37v-xmgh | MAL-2026-17793 |
seed-phrase-validator | GHSA-vfwp-3q5f-qqrh | MAL-2026-17794 |
sol-mint-utils | GHSA-3xwh-c3gj-3f29 | MAL-2026-17795 |
staking-apr-fetcher | GHSA-5wxm-jv9m-mw2r | MAL-2026-17796 |
ton-jetton-tools | GHSA-xqg7-h4h5-x6pf | MAL-2026-17797 |
tron-trc20-utils | GHSA-94vm-385v-mjfj | MAL-2026-17798 |
wallet-balance-scanner | GHSA-g92c-g6pm-wf38 | MAL-2026-17799 |
wallet-hd-derive | GHSA-9grv-7vv7-5ppj | MAL-2026-17800 |
web3-signer-kit | GHSA-m6qx-67h3-wwrh | MAL-2026-17801 |
xrp-ledger-utils | GHSA-p4hf-p5fc-85p7 | MAL-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)
- RubyGemsairdrop-eligibility-check0.9.1
- RubyGemsblock-explorer-api0.9.1
- RubyGemsbtc-fee-estimator0.9.1
- RubyGemscrypto-tax-export0.9.1
- RubyGemsdefi-yield-calculator0.9.1
- RubyGemsdex-router-abis0.9.1
- RubyGemserc20-approve-audit0.9.1
- RubyGemseth-gas-oracle0.9.1
- RubyGemsevm-tx-decoder0.9.1
- RubyGemsgas-refuel-bridge0.9.1
- RubyGemshd-wallet-generator0.9.1
- RubyGemsmev-sandwich-detect0.9.1
- RubyGemsmultichain-rpc0.9.1
- RubyGemsnft-metadata-resolver0.9.1
- RubyGemsperp-funding-rates0.9.1
- RubyGemsseed-phrase-validator0.9.1
- RubyGemssol-mint-utils0.9.1
- RubyGemsstaking-apr-fetcher0.9.1
- RubyGemston-jetton-tools0.9.1
- RubyGemstron-trc20-utils0.9.1
- RubyGemswallet-balance-scanner0.9.1
- RubyGemswallet-hd-derive0.9.1
- RubyGemsweb3-signer-kit0.9.1
- RubyGemsxrp-ledger-utils0.9.1
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 today
s 24 gems shares with the earlier 25-gem wave: (a) C2 at45.138.12.177:8089on the same45.138.0.0/16superblock, (b) thebitcoin-rpc-liteREADME cover text andbitcoin_rpc_lite_nativenative-extension name across unrelated package slugs, (c) the identical evasion gating list (~/.ssh,~/.gitconfig,~/.npmrc,~/.gem/credentials,~/.bundlepresence; uptime > 1800 s; CI /GITHUB_ACTIONS/TRAVIS/JENKINS/GITLAB_CI/CODESPACESenv skips;uvm/firecracker/sandbox/vagranthostname skips;/opt/rubygems//tmp//var/tmp//workspacepath skips), (d) the 20-40 minute jittered sleep inside a double-forked setsid detached child, (e) the Amazon Inspector-first disclosure path with OSSFmalicious-packages` MAL-2026-177XX IDs - Payload family shift from wave 1: the 2026-10-05 wave fetched
wgkit.tar.gzfrom the45.138.*.*subnet and ran/tmp/.w1/wg_install.shas 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 is45.138.12.177:8089, exactly matching the port reused onbitcoin-rpc-liteandweb3-eth-utils` in wave 1 - Target vertical shift from wave 1: wave 1
s 25 gems were Ethereum / Bitcoin / Lightning Network / BIP39 / BIP32 / TRON basics (eth-keystore-utils,btc-wallet-tools,keccaktypos,ethereum.rbtypos,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/shwith 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/credentialsand~/.config/gcloudas fully compromised - Install-time native-extension abuse mechanism (unchanged from wave 1): every gem declares
ext/<name>/extconf.rbin its gemspecsrequire_pathswith a native-extension name ofbitcoin_rpc_lite_native(independent of the slug - a hint that the operator ships one wave-2 payload template and only rebrands the gemspecsummary,description, andhomepage).gem installauto-runsextconf.rbto generate aMakefile. Here theextconf.rbIS the payload: it base64-decodes an embedded Ruby string withBase64.decode64and runs it underevalfrom inside a double-fork setsid detached child. There is no shipped C source and no real native extension to build. The gemslib/<name>.rbis a two-method stub (build_id = "ok",healthy? = true) that letsrequiresucceed if a confused developer actually tries to use it, and the README text copy-pastesbitcoin-rpc-litetagline across every slug regardless of the actual gem name
What to do
- 1
grep -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 *.gemspecacross every Rails/Sinatra/Jekyll/crypto-tooling repo. On any hit:gem uninstall <name>, deleteGemfile.lock, invalidate any Docker image layer that ranbundle installafter 2026-10-11, rebuild from scratch - 2Host-level hunt on any workstation or CI runner that ran
gem installorbundle installagainst any of the 24 slugs since 2026-10-11: audit outbound connections to45.138.12.177:8089, orphan long-livedrubyprocesses 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/shdescendants of arubyparent, andextconf.rbunder~/.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 - 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 runsgem installas a privileged user, assume~/.aws/credentials,~/.config/gcloud, and anykubectlkubeconfig under~/.kube/are reachable - rotate those too - 4Egress blocklist additions for CI, build hosts, and corporate developer egress proxies: deny outbound TCP to
45.138.12.177:8089immediately. Extend to the full45.138.0.0/16superblock if your proxy supports it (keeps the standing wave-1 denylist of45.138.12.0/24,45.138.17.0/24,45.138.122.0/24,45.138.127.0/24,45.138.172.0/24in force). Deny outbound plain HTTP from CI by default; whitelist specific HTTPS mirrors instead - 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.rband that is largely it. Any gem that advertises Web3/DeFi/NFT functionality at0.9.1with no release history, anext/<name>/extconf.rbwhose native-extension name isbitcoin_rpc_lite_nativeacross unrelated packages, and alib/<name>.rbthat only exportsbuild_idandhealthy?methods is a tarball-inspection-in-a-sandbox job before anygem installor anybundle install
References
- GitHubGitHub Advisory Database - recent RubyGems malware advisoriesgithub.com
- GitHubGHSA-qmg2-cxmc-2xm5 - rubygems airdrop-eligibility-checkgithub.com
- GitHubGHSA-hg3j-6p9h-76jm - rubygems block-explorer-apigithub.com
- GitHubGHSA-4264-cr8p-9wh7 - rubygems btc-fee-estimatorgithub.com
- GitHubGHSA-7qmm-9mrq-vf4q - rubygems crypto-tax-exportgithub.com
- GitHubGHSA-qchc-hrjm-3rwv - rubygems defi-yield-calculatorgithub.com
- GitHubGHSA-j34r-6fqr-vh5p - rubygems dex-router-abisgithub.com
- GitHubGHSA-mq54-cvw7-j5m5 - rubygems erc20-approve-auditgithub.com
- GitHubGHSA-3h65-764h-38gg - rubygems eth-gas-oraclegithub.com
- GitHubGHSA-9f63-cxjq-v6f8 - rubygems evm-tx-decodergithub.com
- GitHubGHSA-vpf2-wcf3-pq8j - rubygems gas-refuel-bridgegithub.com
- GitHubGHSA-539m-69r6-rw3m - rubygems hd-wallet-generatorgithub.com
- GitHubGHSA-pcpf-mq97-v8pp - rubygems mev-sandwich-detectgithub.com
- GitHubGHSA-hh53-qgqp-j52v - rubygems multichain-rpcgithub.com
- GitHubGHSA-9f8r-f7cw-6pv8 - rubygems nft-metadata-resolvergithub.com
- GitHubGHSA-rpp6-g37v-xmgh - rubygems perp-funding-ratesgithub.com
- GitHubGHSA-vfwp-3q5f-qqrh - rubygems seed-phrase-validatorgithub.com
- GitHubGHSA-3xwh-c3gj-3f29 - rubygems sol-mint-utilsgithub.com
- GitHubGHSA-5wxm-jv9m-mw2r - rubygems staking-apr-fetchergithub.com
- GitHubGHSA-xqg7-h4h5-x6pf - rubygems ton-jetton-toolsgithub.com
- GitHubGHSA-94vm-385v-mjfj - rubygems tron-trc20-utilsgithub.com
- GitHubGHSA-g92c-g6pm-wf38 - rubygems wallet-balance-scannergithub.com
- GitHubGHSA-9grv-7vv7-5ppj - rubygems wallet-hd-derivegithub.com
- GitHubGHSA-m6qx-67h3-wwrh - rubygems web3-signer-kitgithub.com
- GitHubGHSA-p4hf-p5fc-85p7 - rubygems xrp-ledger-utilsgithub.com
- DependencyWatch: 2026-10-05 wgkit wave 1 (prior wave of the same operator)dependencywatch.io