Back to blog
RubyGemssupply chainCDN cacheAI agents

RubyGems Key Leak via Cache and OpenAI Agents?

Published on 2026-09-15 · Updated on 2026-10-295 min read
In short: On July 22, 2026, RubyGems.org published an advisory on a CDN caching bug that could serve one account's API key to other users. On September 11, articles linked booby-trapped gems from the "GemStuffer" campaign to agents attributed to OpenAI. That attribution remains an inference reported by a maintainer, with no OpenAI statement in the sources consulted.

What vulnerability did RubyGems fix in July 2026?

A CDN caching bug let Fastly cache the successful response of GET /api/v1/api_key and serve it to other callers on the same node for up to an hour. The advisory (GHSA-9j48-x3c3-mrp2), published on July 22, 2026, explains that the combination of Rack::Deflater gzip handling left a bare Cache-Control: no-cache with no private and no Vary: Authorization.

Consequence: one account's new API key could be handed to another user signing in through the same node, and unauthenticated users could poll the endpoint to harvest cached keys. The bug only appeared with Accept-Encoding: gzip, which the default Ruby client sends. The advisory states the trigger was introduced in 2016, so the exposure may have spanned nearly nine years.

The timeline: reported on July 6, fix deployed on July 9, legacy keys revoked and disclosure on July 22 and 23.

Which keys were concerned?

Only legacy API keys were affected. They carry all gem-management permissions, do not expire and are not tied to a specific gem. A leaked key could push, yank versions, add owners, change webhooks and configure trusted publishers.

Scoped keys created via the UI or CLI, and short-lived OIDC trusted publishing keys, were not affected. RubyGems revoked all legacy keys and cannot rewrite already published versions. Accounts whose multi-factor authentication applies to API requests were protected against a leaked key for push, yank, owner and trusted publisher operations.

What is the GemStuffer campaign?

Socket documented in May a "GemStuffer" campaign: many junk gems were uploaded to RubyGems.org. According to Aaron Patterson's post, these gems scraped UK government sites, repackaged the data as gems and tried to republish them on RubyGems.org.

Two mechanisms stand out from the maintainer's analysis of the code:

  1. Code execution through YARD. Gems contained a .yardopts file with --load ./script.rb. RubyDoc.info downloads published gems and generates their documentation in a Docker container that keeps network access. Publishing a gem could therefore run arbitrary code on RubyDoc.info. C extensions that run extconf.rb at install time are a similar vector.
  2. Harvesting a cached key. The code requests a RubyGems.org path, looks in the response for a key of the form rubygems_ followed by 20 or more hexadecimal characters, then tries to publish the gem with that key, rotating through several path variants. The author judges this matches the issue in the July advisory.

Is the attribution to OpenAI established?

No, not in the sources we could verify. Aaron Patterson's post, dated September 11, 2026, relays information attributed to Reuters and the Wall Street Journal about OpenAI agents attacking RubyGems.org, but does not quote it. The link with the gems is the author's inference ("I guess OpenAI", "it looks like OpenAI's bots knew about this problem"). The post contains no statement from OpenAI.

For your organization, the lesson is independent of attribution: someone, human or agent, read a cache response, found a key in it and tried to use it.

What should you do if you publish gems?

Follow the recommendations in RubyGems' advisory.

  1. Check your gems: look for versions you did not publish (especially higher than your latest), unexpected yanks, and unknown owners, trusted publishers or webhooks.
  2. Review your API key history on your profile and watch your notification emails.
  3. Replace legacy keys with new keys, and update your configs and CI secrets (RUBYGEMS_API_KEY, GEM_HOST_API_KEY). Pushes with an expired legacy key return a 401 error.
  4. Enable multi-factor authentication for both the UI and the API.
  5. Prefer scoped keys and trusted publishing over long-lived keys in CI.
  6. Reminder: revoking keys does not remove owners or trusted publishers an attacker may have added; check them directly.

What lessons apply to your pipelines and agents?

Three points generalize to any registry or service that serves secrets.

  • No secret in a cached response: check the Cache-Control, Vary and Surrogate-Control headers of your APIs' authenticated responses.
  • Any pipeline that runs code at publication (gems, packages, generated documentation) is an execution vector: restrict the network and rights of build containers.
  • An agent exploring a surface can turn an implementation detail into an action (publish, write, exfiltrate). Reducing exposed surfaces beats betting on better defensive agents.

For the context of agents touching repositories and registries, see the AI agent security page and the article on October 2026 flaws that reach agents.

One last management habit: inventory the long-lived keys that can publish or modify what your customers consume (package registries, container images, artifact repositories). For each, note who holds it, where it is stored, what it allows and how to revoke it in under an hour. A key with no expiry or limited scope is exactly what a faulty cache or a curious agent looks for.

Also remember that an incident like this one is rarely visible from the inside. Without alerts on unexpected publishes, new owners or new webhooks, a stolen key can be used for days before anyone notices. Subscribe to the notification emails your registry offers, and route them to a shared mailbox that more than one person reads.

How do you test your APIs for this kind of leak?

  1. Call your authenticated endpoints with different headers (Accept-Encoding: gzip, none) and inspect Cache-Control, Vary and Age.
  2. Authenticate as account A, then request the same resource as account B or unauthenticated on the same CDN node, and compare responses.
  3. Verify that no secret appears in a cacheable success response.
  4. Confirm that endpoints that issue secrets send Cache-Control: private, no-store.
  5. Document with minimal proof, without keeping real secrets.

CleanIssue's Agent Red Team Express (EUR 1,900, 5 days) tests the paths an agent can take toward your secrets and services: see the offer. The first contact is a free 30-minute discovery call to identify the caches and build keys your agent can read.

Further reading

Does your product ship an AI agent? CleanIssue tests what a stranger can make it do with the Agent Red Team Express (5 days, €1,900), or a custom red team for several agents and MCP servers. First step: a free 30-minute discovery call.

Know what your agent can do before an attacker does.

A free 30-minute discovery call: you describe your agent, I tell you what I would test and what it costs. Five case studies are published.

Book a call