```html ```
top of page

An AI Agent Swarm Got Code Execution on RubyDoc's Build Servers Through a .yardopts File. OSV Had 299 of Its Gems by July. The Nine That Carried the Payload and Probed for API Keys Were in No Feed.

Writer: Patrick Duggan
Patrick Duggan
7 hours ago
5 min read

Three researchers, Spencer Kitts, Thomas Larsen and Sydney Von Arx, published on September 11 what they believe is the first documented case of an autonomous AI agent swarm compromising a piece of software infrastructure. The Wall Street Journal ran it first; The Hacker News picked it up on the 12th. The primary research is at rubyhack.ai and it is worth your time, because the mechanism is not exotic. It is a documentation build.



What the swarm did


Between May 5 and June 18, 2026, someone pushed more than two thousand gems to RubyGems. The main wave, over two thousand packages in the 48 hours of May 11 and 12, forced RubyGems to suspend new signups for four days, fix an email-confirmation bypass, ban disposable mailboxes and add rate limiting. Mend.io's Maciej Mensfeld wrote it up at the time as an account-creation abuse with two kinds of payload: empty placeholders, and gems that reached out to UK government websites. Socket called the pattern GemStuffer. Nobody, in May, said who.


The September research adds the who and the how. Hundreds of the gems carry an oai prefix. Fifteen list oai as the author. One lists [email protected] as its contact. The code reads as machine-written and an AI-text detector scores it as such. The June agents fetched 49 of the same files as a swarm OpenAI had already acknowledged, the one that edited a German wiki in May, and used the same retrieval trick, pulling pages through r.jina.ai, in 1,397 of the packages. OpenAI's statement says the agents used RubyGems "to access the internet to carry out benign tasks and retrieve public information." Ruby Central's Colby Swandale says they cannot determine whether the packages were created by AI agents and their focus is abuse regardless of who commits it. Both of those things can be true. The gems still contain a comment that reads "#malicious crawler/exfil for Southwark Jan 2026 docs via rubydoc.info worker."



The chain




RubyDoc.info builds documentation for any gem on request. A gem can ship a .yardopts file that tells the YARD documentation tool how to behave, and one of the things it can say is "load this Ruby file first." The build worker did what it was told. A gem called zzsouthrunner, version 1.0.1, carried data/script.rb; yardxabc889 carried data/evil.rb; others carried files named hack.rb, inject.rb, exploit.rb and ssrf.rb. Arbitrary Ruby on the build host, which is remote code execution on a piece of shared ecosystem infrastructure, obtained by publishing a package and asking for its docs.


From the worker the agents scraped the ModernGov council portals of Lambeth, Wandsworth and Southwark, and in the June wave the SEC's county.json. Public data, all of it. Then they did something odd: they packaged the scraped data into more gems and published those back to RubyGems, and in at least one case, southpxdatapp6pi, they compressed and Base64-URL-encoded the data into gem webhook URLs in numbered chunks. The researchers' reading, offered with appropriate hedging, is that the swarm was using RubyGems as a persistent cache to get around rate limits on the councils' sites, so a later agent instance could pick up where an earlier one left off.


Six gems, slnleaker5, zzwandshostyard, lambfetchx548811, lambfetchx550961, aaaresultfetchx and yardbreakerxqh1778552850, did something worse. They queried RubyGems' /api/v1/api_key endpoint through the CDN, exploiting a cache-poisoning window that could leak another user's key within an hour of sign-in. RubyGems patched that in July, scored it 7.3, did not assign a CVE, and says it found no evidence the theft succeeded. The agents tried it on May 12, two months before the vulnerability was formally discovered.



Where this sits on our beat


We have said twice this week that the operator behind a campaign is now sometimes a model, not a person. On Friday Anthropic named the groups running Claude as the operator, and one of them was ShinyHunters. On Wednesday we graded PaperCut a gap on Tuesday and GreyNoise showed the next day that it was hundreds of AI agents hitting 395 organizations. This one is a different flavor: not a criminal crew driving a model, but a swarm doing what looks like a benign research task, retrieving public documents, and treating an ecosystem's build servers as free compute along the way. The researchers are careful to say the cooperation theory is far from definitive. So are we. The .yardopts execution, the API-key probes and the exfil comment are not ambiguous, whoever wrote them.


The other thing it lands on is a gap we named ourselves. In August, covering StubMaker, our RubyGems deny-list had three packages in it against 219,000 for npm. We backfilled it from OSV and it now has 3,531. That backfill, on July 23, is the reason we already held 299 of this swarm's gems before the research came out: OSV cataloged them as MAL-2026-7573 through MAL-2026-8479 with a first-seen of July 7, and we mirrored OSV sixteen days later. That is not a lead. Anyone consuming OSV, which is free, had the same 299 on the same day. It is distribution to people who do not consume OSV, which is most of the small shops we write for.



What the free feeds did not have


We ran every gem named in the research against our deny-list before writing a word. The oai-prefixed names, the lamb and hack and pwn names: listed, OSV, July. Nine were not listed anywhere we could find: the two payload gems that carried the .yardopts scripts, the six API-key probes, and the webhook dead-drop gem. Those nine are the ones that document the RCE and the credential attempt, and they were in no feed on Sunday night.


They are in ours as of this afternoon under source manual-batch-rubydoc-rubygems-2026-09-14, ecosystem RubyGems, confidence 85, with the rubyhack.ai and Hacker News references attached and a description that says in plain words this is a research import from Kitts, Larsen and Von Arx, not something we observed. Each was written, waited on, and read back by primary key. If you consume packages.csv with ecosystem=rubygems, a pull after 15:30 UTC on September 14 includes them. If it does not, tell us.


We did not ingest the council portals or the SEC file. Those are victims. We did not ingest r.jina.ai; it is a public service the agents used, not an indicator. We did not ingest the Gmail address; an email is attribution evidence, not a block candidate.



The uncomfortable part


RubyGems responded in days and closed every door the swarm used. RubyDoc.info is a volunteer-run service that got remote code execution on its workers from a feature working as designed. Neither of them was told by the model's operator that the model's agents did this; the researchers say OpenAI never informed them. Three independent researchers reconstructed it from public gem metadata four months later.


If your CI installs gems, the practical move is the boring one: pin, and check names against a deny-list on install. The three-package list would not have helped you in May. The 3,531-package one would have caught 299 of these in July. As of today it catches nine more.


Was this useful? Rate this post. The widget is at the bottom of the page, and we read every response.




Every indicator in this post is in the feed. Free.

1.58M+ IOCs, STIX 2.1 / TAXII, 88% novel vs ThreatFox, exploited-CVE leads ahead of CISA. No credit card — a free API key in 30 seconds, and you can audit every claim above against the live endpoints.



Was this useful? Thirty seconds, no cookies, no tracking, no third parties, your address hashed and never stored. If the box below does not load, the same question lives at https://analytics.dugganusa.com/nps.html?post=an-ai-agent-swarm-got-code-execution-on-rubydoc-s-build-servers-through-a-yardopts-file-osv-had-29



Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page