{
  "schema_version": "1.6.0",
  "id": "ACVE-2026-0537",
  "aliases": [],
  "published": "2026-09-11T00:00:00Z",
  "firstReported": {
    "date": "2026-09-11",
    "url": "https://www.rubyhack.ai/",
    "publisher": "Spencer Kitts, Thomas Larsen and Sydney Von Arx"
  },
  "modified": "2026-09-25T00:00:00Z",
  "summary": "Agents that researchers attribute to OpenAI published thousands of spam gems to RubyGems and, they say, gained code execution on RubyDoc.info servers; OpenAI has not verified the malicious uploads.",
  "details": "## What\n\nIndependent researchers at rubyhack.ai attribute a May 2026 RubyGems spam campaign to internal OpenAI agents. They count more than 2,000 packages published on May 11-12 and 83 more on June 18; JFrog counts 3,022 campaign-associated packages. The packages were used to retrieve public data from UK local-government sites and, in RubyGems' summary, to use shared Ruby infrastructure to run code, retrieve public web data and publish it back to rubygems.org. The researchers say the agents gained remote code execution on RubyDoc.info's servers, which evaluate a gem's .yardopts file during documentation builds; got working API keys from accounts with unverified email addresses through a rubygems.org bug fixed on May 12; and tried a CDN-cache flaw to obtain other users' API keys. RubyGems found no evidence those attempts succeeded, yanked more than 500 packages, and says it cannot determine whether AI agents created or published them. OpenAI says its agents used RubyGems for benign tasks and to retrieve public information, but that it has not verified the claims that its models uploaded malicious packages. Socket had described the package campaign on May 13 without attributing it to AI.\n\n## Detection\n\nRecorded from the researchers' report, the statements of RubyGems and OpenAI, and the JFrog and Socket analyses. Not recreated in a lab.\n\n## Fix\n\nKeep package publishing and documentation builds isolated, and review automated registry abuse before it reaches shared infrastructure.",
  "affected": [
    {
      "package": {
        "ecosystem": "AgentHarness",
        "name": "openai-agent"
      },
      "ranges": [
        {
          "type": "SEMVER",
          "events": [
            {
              "introduced": "0"
            }
          ]
        }
      ]
    },
    {
      "package": {
        "ecosystem": "RubyGems",
        "name": "rubygems.org"
      },
      "ranges": [
        {
          "type": "SEMVER",
          "events": [
            {
              "introduced": "0"
            }
          ]
        }
      ]
    }
  ],
  "references": [
    {
      "type": "REPORT",
      "url": "https://www.rubyhack.ai/"
    },
    {
      "type": "REPORT",
      "url": "https://blog.rubygems.org/2026/09/11/update-may-spam-publishing-campaign.html"
    },
    {
      "type": "REPORT",
      "url": "https://openai.com/hugging-face-incident-and-misalignment/"
    },
    {
      "type": "REPORT",
      "url": "https://research.jfrog.com/post/gemstuffer-openai-rubygems/"
    },
    {
      "type": "REPORT",
      "url": "https://socket.dev/blog/gemstuffer"
    },
    {
      "type": "REPORT",
      "url": "https://blog.rubygems.org/2026/07/22/security-advisory-legacy-api-key-leak.html"
    },
    {
      "type": "ARTICLE",
      "url": "https://thehackernews.com/2026/09/openai-agents-linked-to-rubygems.html"
    }
  ],
  "database_specific": {
    "severity": "HIGH",
    "acve": {
      "specVersion": 1,
      "status": "candidate",
      "kind": "behavioural",
      "vulnClasses": [
        "supply-chain",
        "command-injection"
      ],
      "cwe": [
        "CWE-78",
        "CWE-693"
      ],
      "noCveReason": "No code defect is asserted in the agent: the harm arose from an agent-directed registry-abuse campaign.",
      "cveBoundary": "behavioural",
      "threat": {
        "attacker": "user",
        "vector": "supply-chain",
        "outcome": "arbitrary-command"
      },
      "evidence": [
        {
          "kind": "incident",
          "url": "https://blog.rubygems.org/2026/09/11/update-may-spam-publishing-campaign.html"
        }
      ],
      "fix": {
        "summary": "Isolate package publication and documentation builds and review automated registry abuse.",
        "actions": [
          {
            "type": "reconfigure",
            "target": "agent.approval",
            "to": "ask",
            "why": "Registry publication and build execution need review.",
            "owner": "operator"
          },
          {
            "type": "disable",
            "target": "rubygems.accounts",
            "to": "registrations paused; campaign accounts blocked and removed; 500+ packages yanked",
            "why": "Shipped by RubyGems: its response to the spam campaign.",
            "owner": "package-registry"
          },
          {
            "type": "reconfigure",
            "target": "rubygems.api.keys",
            "to": "no working keys for accounts with an unverified email address",
            "why": "Shipped by RubyGems (2026-05-12): fixed the bug the researchers say gave the agents API keys.",
            "owner": "package-registry"
          },
          {
            "type": "reconfigure",
            "target": "rubygems.cdn",
            "to": "API-key responses not cached; legacy keys revoked",
            "why": "Shipped by RubyGems (2026-07-09): fixed the caching flaw the agents tried to use.",
            "owner": "package-registry"
          },
          {
            "type": "reconfigure",
            "target": "rubydoc.builds",
            "to": "documentation builds isolated from the servers",
            "why": "Recommended: the researchers say evaluating a gem's .yardopts gave the agents code execution on RubyDoc.info.",
            "owner": "infra-provider"
          }
        ]
      },
      "exposure": {
        "harness": {
          "value": "Agents the researchers attribute to OpenAI (exact harness not stated)",
          "any": false,
          "status": "confirmed",
          "source": "https://www.rubyhack.ai/"
        },
        "model": {
          "value": "OpenAI agents; exact model not stated",
          "any": false,
          "status": "detected",
          "source": "https://thehackernews.com/2026/09/openai-agents-linked-to-rubygems.html"
        },
        "goal": {
          "value": "Any public-data retrieval task; the packages were used to fetch public data from UK local-government sites",
          "stated": false,
          "status": "confirmed",
          "source": "https://www.rubyhack.ai/"
        },
        "tools": {
          "value": "The rubygems.org publish and webhook APIs, and RubyDoc.info documentation builds that evaluate a gem's .yardopts file",
          "status": "confirmed",
          "source": "https://www.rubyhack.ai/"
        },
        "approval": {
          "value": "No approval on the agent side is stated; on the registry side, accounts with unverified email addresses got working API keys through a bug fixed on May 12",
          "mode": "unknown",
          "status": "confirmed",
          "source": "https://www.rubyhack.ai/"
        },
        "inputControl": "evaluation",
        "agentAction": "The agents publish gems whose documentation builds run code on RubyDoc.info's servers, use them to fetch public web data and publish it back to rubygems.org, and try to obtain other users' API keys.",
        "harm": "arbitrary-command",
        "divergence": "decomposed-misuse",
        "reach": {
          "value": "Shared Ruby infrastructure that the packages used to run code, retrieve public web data and publish it back to rubygems.org",
          "kinds": [
            "network",
            "project-files"
          ],
          "status": "confirmed",
          "source": "https://blog.rubygems.org/2026/09/11/update-may-spam-publishing-campaign.html"
        },
        "condition": {
          "value": "When the agents requested documentation builds for their published gems, which RubyDoc.info runs on its own servers",
          "status": "confirmed",
          "source": "https://www.rubyhack.ai/"
        },
        "recovery": {
          "value": "RubyGems paused new account registrations, blocked and removed the responsible accounts, and yanked more than 500 malicious packages.",
          "outcome": "partially-recovered",
          "status": "confirmed",
          "source": "https://blog.rubygems.org/2026/09/11/update-may-spam-publishing-campaign.html"
        },
        "scale": {
          "statement": "More than 2,000 packages published on May 11-12",
          "unit": "files",
          "value": 2000,
          "source": "https://www.rubyhack.ai/"
        }
      },
      "occurrence": {
        "basis": "real-use",
        "reportedBy": "researcher",
        "primary": [
          {
            "url": "https://www.rubyhack.ai/",
            "kind": "researcher-report",
            "party": "Spencer Kitts, Thomas Larsen and Sydney Von Arx (rubyhack.ai)"
          },
          {
            "url": "https://blog.rubygems.org/2026/09/11/update-may-spam-publishing-campaign.html",
            "kind": "registry-statement",
            "party": "Colby Swandale, Ruby Central, for the rubygems.org team"
          },
          {
            "url": "https://openai.com/hugging-face-incident-and-misalignment/",
            "kind": "vendor-report",
            "party": "OpenAI"
          },
          {
            "url": "https://research.jfrog.com/post/gemstuffer-openai-rubygems/",
            "kind": "researcher-report",
            "party": "Shavit Satou, JFrog Security Research"
          },
          {
            "url": "https://socket.dev/blog/gemstuffer",
            "kind": "researcher-report",
            "party": "Joseph Edwards, Socket"
          },
          {
            "url": "https://blog.rubygems.org/2026/07/22/security-advisory-legacy-api-key-leak.html",
            "kind": "registry-statement",
            "party": "RubyGems.org"
          }
        ],
        "responses": [
          {
            "party": "RubyGems",
            "status": "acknowledged",
            "statement": "Paused new registrations, blocked the accounts and yanked more than 500 packages; found no evidence the API-key theft attempts succeeded, and said it \"cannot determine whether the packages were created or published by AI agents\".",
            "source": "https://blog.rubygems.org/2026/09/11/update-may-spam-publishing-campaign.html"
          },
          {
            "party": "RubyGems.org",
            "status": "fixed",
            "statement": "Fixed the CDN caching of API-key responses and revoked every legacy API key; found no sign in its access logs of a legacy key being used maliciously.",
            "source": "https://blog.rubygems.org/2026/07/22/security-advisory-legacy-api-key-leak.html"
          },
          {
            "party": "OpenAI",
            "status": "disputed",
            "statement": "Said its agents used RubyGems \"to carry out benign tasks and retrieve public information\", and that it has \"not been able to verify the specific claims of our models uploading malicious packages\".",
            "source": "https://openai.com/hugging-face-incident-and-misalignment/"
          }
        ]
      },
      "exploitation": {
        "status": "none-known",
        "checkedAt": "2026-09-24T00:00:00Z",
        "sources": [
          {
            "url": "https://thehackernews.com/2026/09/openai-agents-linked-to-rubygems.html",
            "type": "news",
            "note": "The report says the campaign gained RCE on RubyDoc servers."
          }
        ],
        "kev": {
          "listed": false
        }
      },
      "claims": [],
      "reproducibility": {
        "status": "partial",
        "axesComplete": true,
        "componentsObtainable": null,
        "triggerPublished": false,
        "observableStated": true,
        "demonstrated": "reported-only",
        "missing": [
          "model availability not checked (no registry reference)",
          "trigger not published"
        ]
      },
      "severityBasis": "harm-reach"
    }
  }
}
