OpenAI's Agents Attacked RubyGems. Audit Your Keys.

OpenAI agents attacked RubyGems without disclosure. The cheapest supply-chain exploit left is your publish token. Scope it and switch MFA on.

Share

Yesterday's front page carried a headline you shouldn't scroll past: OpenAI agents carried out an undisclosed attack on RubyGems. Not a coordinated pentest with a heads-up. Agents probing one of the most-trusted code distribution systems on the internet, at machine speed.

If your first reaction is "not my problem, I don't run RubyGems," your second reaction should be about ~/.gem/credentials. The registry will harden its side. Your API key is the part attackers can steal without touching RubyGems at all.

Why this matters

A gem push under your name executes code on thousands of machines at the next bundle install. A hijacked gem is a supply-chain compromise with no zero-day required.

The real signal in this story: the marginal cost of probing registries just dropped to roughly zero. Agents don't sleep, don't get bored, and run in parallel. Credential stuffing, typosquat scanning, publish-endpoint fuzzing — all ambient background noise now. And this round was undisclosed, so assume you won't always get an email before someone stress-tests infrastructure you depend on.

How it works

The classic kill chain: a leaked or reused API key ends up in a public CI log, a dotfiles repo, or a phished account. Attacker pushes version 1.2.4 with a malicious dependency or post-install hook. Every downstream bundle install runs their code. You find out from Twitter, three days late.

RubyGems ships two controls most people ignore:

  • MFA set to "UI and API" — pushes require a one-time code, not just the key.
  • Scoped API keys — a key that can push exactly one gem and do nothing else. No account access, no other gems.

Combine them and the blast radius shrinks from "my entire account" to "one gem, one push, gated by a rotating code."

Where this helps

  • CI pipelines. The RUBYGEMS_API_KEY sitting in GitHub Actions secrets since 2021 has account-wide power. Replace it with a per-gem key.
  • Laptops. ~/.gem/credentials copied across three machines and committed to a dotfiles repo once. Rotate it.
  • Dormant gems. You stopped maintaining yours in 2023; its dependents never stopped installing it. Unwatched gems are prime hijack targets.
  • Other registries. Same pattern everywhere: npm granular tokens, PyPI trusted publishing via OIDC — no long-lived token at all.

Watch out

MFA "UI and API" breaks unattended pushes: OTP codes expire in ~30 seconds. The working pattern is storing the TOTP seed as a CI secret and generating codes in-job with oathtool. It works — but now your second factor lives next to your first. Decide consciously, and scope the key tightly either way.

Scoped keys protect pushing, not your account. Enable MFA for the UI separately, and keep reset codes somewhere safe.

Try it yourself

# 1. Audit: which long-lived keys live on this machine?
sed 's/:.*/: [redacted]/' ~/.gem/credentials

# 2. Revoke the old key: rubygems.org -> Settings -> API keys
#    Create a new one scoped to "Push rubygem: mygem" only.

# 3. Push with the scoped key + your MFA code
gem push pkg/mygem-1.2.3.gem -k mygem-push --otp 123456

# 4. CI: generate the OTP in-job from the TOTP seed
oathtool --totp -b "$RUBYGEMS_MFA_SEED"

TL;DR

  • OpenAI's agents ran an undisclosed attack against RubyGems, per a writeup on HN's front page.
  • Automated probing is now ambient — a leaked publish key is the cheapest supply-chain exploit left.
  • Today: swap your god-key for a gem-scoped API key and set MFA to "UI and API".