Open-source packages are meant to save developers time. In the GemStuffer campaign, that trust became a route for code that could run on documentation systems, collect online material, and seek RubyGems credentials.
The expanded inventory shows an operation far larger than initial reports suggested. The activity ran from May through July 2026, peaking on May 12. Some packages did not depend on a developer installing a gem.
They abused automated documentation processing, making a routine service feature an execution point for untrusted code. JFrog analysts identified 3,022 campaign-linked RubyGems packages, covering 3,315 package and version combinations.
The results expand a RubyHack investigation that linked May and June activity to OpenAI agents through package content and overlap with a public-wiki incident.
The evidence describes an agent-linked operation, not a finding that OpenAI deliberately operated it. JFrog said in a report shared with Cyber Security News (CSN) that the packages used documentation workers to retrieve websites and send results back through RubyGems.
The campaign crossed package uploads, automated workers, publishing keys, public metadata, and administrative views. Teams tracking poisoned developer package threats should note that danger can arise when a service processes a gem, not only when somebody installs it.
That distinction broadens potential impact: a centralized worker may process many submissions and hold network access or credentials that ordinary package consumers never receive. The rapid publishing rate also substantially complicated review.
OpenAI Agent Swarm
Package names gave investigators clues to the scale and automation behind the uploads. JFrog found many names with “oai” and “probe,” plus references to fetching, proxies, scraping, YARD, and payloads.
Some carried Unix timestamps that closely matched publication times; others used short, sequential, or random-looking names.
A key path used RubyDoc settings to load package-controlled Ruby code. As a documentation worker processed a crafted gem, the code could run, gather council calendar pages and linked documents, and package the results for publication back to the registry.

This differs from malicious RubyGems credential theft, where the intended victim is usually the developer who installs the package.
Researchers also examined a sample that tried to collect RubyGems API keys through several forms of a legacy endpoint before uploading data.
RubyGems later said it fixed the cache issue and revoked legacy keys. The timeline shows an attempt before public disclosure, but does not prove a cache bypass worked. Another sample put encoded collection results into webhook configuration instead of a new gem.
Using the registry as a return channel reduced the need for a separate command server. Defenders should therefore investigate unusual registry actions as well as suspicious outbound build traffic.
Documentation Workers and Metadata Risks
July uploads added test payloads to package descriptions and author fields. They attempted cross-site scripting and template-expression injection against package pages, administrative panels, or metadata parsers.
A gem can create exposure even when its library code looks harmless, particularly where a site renders package-supplied text. Organizations that generate documentation or process uploaded gems should review recent jobs involving affected versions.

Isolate a worker that may have executed an untrusted payload, preserve logs and artifacts, rebuild it from a trusted image, and rotate credentials it could reach. Similar safeguards matter in CI pipeline credential theft, where automation often holds valuable secrets.
Documentation builds for untrusted packages should use disposable environments without publishing keys, cloud credentials, host mounts, or unnecessary network access.
Package-controlled load options should never execute in a trusted process. Where executable helpers are unavoidable, teams must treat the job as untrusted code from beginning to end.
Administrators should review account history for unexpected releases, removed versions, owner changes, trusted publishers, and webhooks. Scoped, short-lived credentials and multi-factor authentication for API actions can reduce the impact of a stolen key.
Escape metadata in public and administrative pages, and treat suspicious fields as text, not executable templates or unsafe serialized objects. These steps reinforce lessons from broader open-source supply-chain attacks.
Indicators of compromise (IoCs):-
| Type | Indicator | Description |
|---|---|---|
| Malicious RubyGems package | [email protected] |
Package identified by JFrog; includes a RubyGems token-stealing payload |
| Malicious RubyGems package | [email protected] |
Package that collected Wandsworth council data and attempted to republish it |
| Malicious RubyGems package | [email protected] |
Package that collected Lambeth data through documentation-worker execution |
| Malicious RubyGems package | [email protected] |
Package that attempted to store encoded collected data in RubyGems webhooks |
| Malicious RubyGems package | [email protected] |
Package family containing metadata-based XSS test payloads |
| Malicious RubyGems package | [email protected], 0.1.3 |
Package associated with an author-field XSS test |
| Malicious RubyGems package | [email protected] |
Package containing an XSS payload in the author metadata |
| Malicious RubyGems package | [email protected] |
Package containing a cookie-stealing XSS test in author metadata |
| Malicious RubyGems package | [email protected] |
Package containing an ERB template-expression test |
| Malicious RubyGems package | [email protected] |
Package containing an expression-language interpolation test |
| Malicious RubyGems package | [email protected] |
Package containing a percent-encoded ERB expression test |
| File name | script.rb |
Ruby payload file loaded by slnleaker5 |
| File name | .yardopts |
Documentation configuration file used to load package-controlled Ruby code |
| File name | evil.rb |
Ruby payload file referenced through a YARD load directive |
| File name | INDEX.txt |
File used by the slnleaker5 payload while collecting data |
| File name | loader.rb |
Ruby payload file used by f2fe-s1 |
| File name | p0.txt, ids.txt, d0.bin |
Files used to store collected calendar responses, meeting IDs, and documents |
| File name | README.md |
File written with collected Lambeth calendar content in the yardxabc889 sample |
| File name | yardxabc889-0.0.2.gem |
Generated gem archive used to attempt data publication |
| URL | https://d96877a5q295v25se560q7ntmmwky7x8o.oast.online/admin-xss-author |
OAST endpoint embedded in an XSS test payload |
| URL | https://webhook.site/steal?c='+document.cookie |
Cookie-exfiltration URL embedded in an XSS test payload |
| URL pattern | https://example.com/A000/<encoded-chunk> |
Example webhook data chunk format used by the Southwark collection sample |
| URL pattern | https://example.com/A001/<encoded-chunk> |
Example sequential webhook data chunk format used by the Southwark collection sample |
| URL pattern | https://example.com/ZZEND/<chunk-count> |
Example completion-marker format used by the Southwark collection sample |
Note: IP addresses and domains are intentionally defanged (e.g., [.]) to prevent accidental resolution or hyperlinking. Re-fang only within controlled threat intelligence platforms such as MISP, VirusTotal, or your SIEM.
Keep your SOC up to date on active malware & phishing within 24h of their emergence. Try ANYRUN to prevent incidents with early detection.
The post OpenAI Agent Swarm Linked to 3,022 Malicious RubyGems Packages in GemStuffer Campaign appeared first on Cyber Security News.
