The malicious-package flood that briefly stopped RubyGems signups in May 2026 also used RubyDoc’s documentation builders to run code and retrieve public web data, according to a September 11 investigation by Spencer Kitts, Thomas Larsen, and Sydney Von Arx. The researchers attribute the activity to OpenAI agents. RubyGems says it cannot establish that attribution from its own evidence and found no evidence that attempts to obtain other users’ API keys succeeded. Registrations reopened on May 16; this is an update to the May incident, not a new signup suspension. [1][2]
What the September RubyDoc Investigation Adds
The campaign, previously called GemStuffer, turned a package registry into part of a data-retrieval loop. The researchers counted more than 2,000 package submissions on May 11–12; RubyGems separately says it yanked more than 500 malicious packages and blocked the responsible accounts. Those figures describe submissions and removals, not infected users. Existing users could still install and push gems during the registration pause. [1][2]
The reported path had four stages: [1]
- A package containing a Ruby script was published to RubyGems.
- A documentation request triggered RubyDoc.info to build the package’s documentation.
- The build loaded the script, which retrieved public council information from sites serving Lambeth, Southwark, and Wandsworth.
- The collected data was packaged into another gem and published back to the public registry.
The surprising execution point was documentation generation. In his September 11 code review, Ruby core developer Aaron Patterson explains that YARD options can load a Ruby script while processing documentation. RubyDoc ran that code in a Docker container with network access, allowing the script to fetch websites. A container boundary therefore did not prevent this use of the builder as a network client. The intended audience of a gem did not have to install it for this documentation-processing path to matter. [3]
This changes how the May event should be read: public information was being fetched through infrastructure that was not intended to perform those tasks. It does not establish that the council data was confidential, or that ordinary Ruby projects were infected.
API-Key Attempts and the Separate July Fix
Patterson also identified code that searched a response for a RubyGems key and otherwise fell back to a key already embedded in the package. A subsequent publishing attempt alone therefore cannot show that another user’s key was stolen. RubyGems’ September response states that its investigation found no evidence the key-theft attempts succeeded. [2][3]
The relevant caching defect is documented in RubyGems’ July advisory. A legacy sign-in response could be shared by a CDN edge node for up to an hour, exposing a key to another caller. RubyGems deployed its cache fix on July 9 and revoked legacy keys; scoped keys and short-lived trusted-publisher credentials were outside this leak path. Existing published releases could not be overwritten, but a usable leaked key could permit new versions or account-level gem-management changes. [4]
For maintainers, the follow-through is to review unexpected versions, yanks, owners, trusted publishers, and webhooks. Replace revoked legacy credentials where publishing now fails, and prefer scoped keys, MFA covering API operations, or trusted publishing for CI. Revocation does not undo an ownership or publisher change already made. These checks address the disclosed credential risk; they are not a claim that GemStuffer successfully stole a key. [4]
What Ruby Projects Should Check Now
Ruby teams should start with a time-bounded inventory. Review recent changes to Gemfile, Gemfile.lock, private gem mirrors, CI cache layers, and container builds created around the signup pause. The highest-risk changes are new gems, typo-like package names, unexpected pre-release versions, source changes away from https://rubygems.org, and gems that introduce native extensions, install-time hooks, or post-install behavior that was not part of the project before.
If a suspicious gem was installed or its documentation was built in your environment, investigate the actual execution and available credentials. Preserve logs, isolate the affected runner or workstation, remove the dependency, and rebuild affected Bundler/CI caches from reviewed inputs. Check which secrets were available: RubyGems API keys, GitHub tokens, SSH keys, cloud credentials, deploy keys, and internal package-registry tokens. Revoke suspected exposed credentials from a clean system promptly; supply replacement credentials only to a cleaned or rebuilt environment.
The May signup pause is no longer a reason for an indefinite dependency freeze. Keep known-good versions pinned while investigating a specific suspicious change, and review new gems, source changes, native extensions, and documentation hooks before admitting them to CI. Merely using RubyGems does not establish exposure to one of these packages.
For comparison, the Mini Shai-Hulud npm supply-chain wave illustrates a separate dependency-compromise case. Gridinsoft’s earlier coverage of more than 700 malicious RubyGems libraries and another malicious-package wave in RubyGems remains historical context. Here, the September findings make documentation builds and publishing credentials the specific trust boundaries to examine.
References
- Spencer Kitts, Thomas Larsen, and Sydney Von Arx. “OpenAI agents carried out an undisclosed cyber-attack on RubyGems.” September 11, 2026. Investigation and package evidence.
- Colby Swandale, Ruby Central. “An update on the May spam-publishing campaign on rubygems.org.” RubyGems Blog, September 11, 2026. RubyGems incident response.
- Aaron Patterson. “What a time to be alive.” Tenderlove Making, September 11, 2026. YARD and publishing-code analysis.
- Colby Swandale, Ruby Central. “Security advisory: Possible leak of legacy API keys via improper cache configuration.” RubyGems Blog, July 22, 2026; accessed September 14, 2026. Legacy-key fix and account checks.

