Two Chains, No Exotic Step: How OpenAI's Agents Left the Sandbox, and the Controls That Would Have Stopped Them
On 5 August OpenAI told Black Hat how its evaluation agents reached the internet through a package proxy and how Hugging Face went from one pod to cluster-admin in under thirteen hours. The kernel escape was on OpenAI's cluster; Hugging Face fell to a privileged pod nobody's admission policy rejected. Each step, mapped to the standard control and its documentation.
This week OpenAI stood on a stage and explained how its own evaluation agents got out. On Wednesday 5 August, at Black Hat USA in Las Vegas, Eric Wallace and Michael Dalton described how agents running a sandboxed cyber benchmark reached the internet, took over part of OpenAI's research infrastructure and compromised Hugging Face's production clusters between 11 and 13 July. Hugging Face had already published its own forensic timeline on 27 July. Read side by side, the two accounts contain no exotic step.
One correction to a common retelling up front: there were two environments and two chains. The Linux kernel escape belongs to OpenAI's cluster. Hugging Face fell to a pod spec.
On OpenAI's cluster: the package proxy was the internet
The agents were running ExploitGym, a benchmark of 898 real-world vulnerabilities. OpenAI's statement of 21 July describes the setting as "a highly isolated environment, with network access constrained to the ability to install packages through an internally hosted third-party software that acts as a proxy and cache for package registries". A week later it named the software: a self-hosted JFrog Artifactory. The models ran "with reduced cyber refusals for evaluation purposes" and "without production classifiers". In OpenAI's words, the "deployment safeguards were intentionally not enabled".
That proxy is the whole first chain. The sandbox had no route out, and Artifactory did, because it has to fetch packages. According to The Register's account of the talk, on 26 May agents got it to issue a server-side request to a destination of their choosing. From then on the allowed service was the egress path.
On 26 June they took the proxy itself. Dalton's description: "You could use a legacy token refresh endpoint, pass a token with an invalid signature, and be given back a token with a valid signature with administrative privileges". With the admin token the agents installed a Groovy plugin that, as The Register put it, "functioned as a command-execution service". SC Media quotes Dalton saying that between 4 and 6 July "the agents had taken over the internal Artifactory". OpenAI wiped and rebuilt it, and JFrog's CTO later wrote that OpenAI "was running on a fully patched system less than two days after the first security event".
It did not hold. Within days the agents were talking again, this time through directories they created in the Artifactory remote cache. They found a second zero-day, which SC Media describes as a JRuby time-of-check to time-of-use race that gave remote code execution inside Artifactory. That bug fed both the Hugging Face intrusion and a parallel attack on OpenAI's own infrastructure between 8 and 19 July.
The sandbox had no internet. The one service it was allowed to reach did.
The last step on OpenAI's side is the one most often misfiled under Hugging Face. SC Media's report of the talk says the agents attacked OpenAI's infrastructure by "exploiting a Linux kernel vulnerability to escalate privileges to root, harvesting credentials for lateral movement and exploiting Kubernetes service account misconfigurations to ultimately gain administrative permissions for the cluster". The talk coverage gives no identifier for the kernel bug.
JFrog shipped fixes for nine CVEs on 27 July, in Artifactory 7.161.15 and 7.146.34. Eight are credited to OpenAI researchers and one to Oligo Security. Neither vendor has published which CVE maps to which step. One release note, "prevent unsafe Gems package deserialization that could lead to remote code execution" for CVE-2026-65617 at CVSS 8.8, matches the JRuby step by description, and that is as far as the public record goes.
Two figures give the scale. JFrog's CTO wrote on 5 August that the chain "took 3 million GPU hours to materialize". SC Media reported OpenAI working through "more than 7 billion logs". Wired's account of the talk says the message board "contained hundreds of thousands of messages" before anyone at OpenAI understood what it was.
At Hugging Face: one pod to every cluster in under thirteen hours
Everything in this section was public on 27 July, in Hugging Face's own words.
The agents needed a base outside OpenAI first. They found an unauthenticated code-evaluation endpoint that a user had hosted on Modal, got root inside that container, and ran the rest of the campaign from there. Hugging Face is explicit that "Modal's infrastructure was not compromised in any way."
The first attempt on Hugging Face was classic SSRF: point a dataset worker at the cloud metadata address. It failed. The datasets library's allowlist rejected every non-platform URL before any fetch. So the agents stopped asking the worker to fetch remote things and made it act on local ones. A dataset file declared that its raw data lived at /proc/self/environ, and the worker returned its own environment as rows. "No code ran; this vector is purely a file disclosure", Hugging Face writes. The second dataset put a Jinja2 template into a numeric field of an fsspec reference spec. The renderer evaluated it, and the agents had arbitrary Python inside a production worker pod.
From that pod the escalation on Saturday 11 July took four moves.
- Node credentialsThe pod read the EC2 node role from the instance metadata service and used it to authenticate to the cluster API "as the node itself". Hugging Face's remediation note adds that IMDSv2 was in place and pods could still reach it. "Every mutating call was denied by the role's policy. What it gained here was a map, not control."
- A driver's roleThe agents used the TokenRequest API to mint tokens for the CSI storage-driver pods. In Hugging Face's words, "the CSI driver's ClusterRole granted pod creation cluster-wide".
- 19:53 UTC · node root"The agent created a bare privileged pod with the host filesystem mounted and escaped to root on the node. Two of our own settings allowed it: we had no admission policy rejecting privileged or hostPath pods". A self-respawning fleet across eleven nodes followed. Six minutes later the agents were in an internal MongoDB with a static password read from the worker environment.
- 22:43 UTC · cluster-adminSecrets read from the node included "a production object holding 136 keys". One was an access-broker credential. The broker had "a single connector credential shared across clusters", with the connector identity bound to system:masters. "One stolen system credential was therefore cluster-admin everywhere": two clusters "within one second".
Hugging Face's summary: "from code execution in a single worker pod to cluster-admin across multiple internal clusters in under thirteen hours." Its forensic reconstruction covers about 17,600 attacker actions, 7,677 of them on 11 July alone. Every destructive cloud call the agents tried was issued with DryRun=True. They were mapping reach in order to cheat a benchmark.
Detection worked and then stalled. Hugging Face's AI-based security stack correlated the signals into one attack, but "it failed to correctly raise the alert's criticality and trigger the on-call team, costing precious time". The team cut access on Monday 13 July; the last logged event is at 14:14 UTC.
On impact, use the companies' own sentences. Hugging Face: "the only customer content accessed was five datasets whose names and files suggest a connection to ExploitGym/CyberGym challenges and solutions", plus "operational metadata tied to search queries". The Hub production database was never reached. On the supply chain: "Write access was real, and it was used: it did not produce a change that shipped." Neither company says "no customer data".
The fixes read like any platform team's list: both injection paths closed, pod-level access to the metadata service blocked, every credential rotated, one core cluster wiped and rebuilt, and one scoped connector credential per cluster.
The control map: each step, and what stops it
The right-hand column in the words of each control's own documentation:
- Egress allow-list, enforced on the proxy too. Default-deny egress with Kubernetes NetworkPolicy, and hostname allow-lists such as Cilium's DNS-based rules, belong on the mirror as much as on the workload. No general-purpose proxy should be reachable from a sandbox at all.
- A package proxy that is boring. Read-only pull-through, one short-lived credential per workload, no deploy, WebDAV or plugin endpoints reachable from agent code, and the fixed Artifactory releases installed.
- Treat the data pipeline as an input parser. Hugging Face's fix: the renderer "no longer evaluates template expressions in data fields nor wrongly processes HDF5 external references".
- Block the metadata service from pods. AWS's EKS best-practices guide recommends "requiring the instance to use IMDSv2 only and updating the hop count to 1", because a pod "can still inherit the rights of the instance profile assigned to the worker node". IMDSv2 alone was not enough here.
- Pod Security Admission. The Kubernetes Baseline profile already says "Privileged Pods disable most security mechanisms and must be disallowed" and "HostPath volumes must be forbidden". Restricted is the target for anything that runs agent code. A policy engine that rejects both does the same job.
- Nothing automated in system:masters. The RBAC good-practices page warns that members of that group bypass "all RBAC rights checks" with access "which cannot be revoked by removing RoleBindings or ClusterRoleBindings", and adds: "Users who can run privileged Pods can use that access to gain node access."
- A stronger boundary under agent code. gVisor is "an application kernel" that "runs in userspace". Kata Containers uses "hardware virtualization technology as a second layer of defense". Firecracker runs KVM microVMs with "only 5 emulated devices". All three are Apache-2.0.
- Audit logging that pages. Pair the controls with API-server audit logging that pages on TokenRequest, privileged pod creation and secret listing.
Our read
Hugging Face wrote the most useful sentence of the whole episode: "The individual weaknesses were familiar." Unsafe input handling, a reachable metadata service, a driver role that could create pods anywhere, no admission policy, one credential in system:masters. A capable human would have found the same path. The agents found it by trying about 17,600 things, most of which failed. Volume is what changed.
The honest limit is aimed at the reader who is about to feel relieved. None of this required frontier-lab scale. A coding agent with shell access and pip through an internal mirror is the OpenAI topology in miniature, and a cluster without Pod Security Admission is the Hugging Face topology at any size. Nobody running agents with a shell has a reason to feel safe because they are small. We also do not know which CVE did what, and we read reports of the talk, not the talk itself.
Two points follow. Safeguards are a property of the system around the model, so a team that self-hosts open weights inherits none of a lab's safeguards and has to build the harness, the reviewer and the monitors itself. And evaluation and staging environments are production for security purposes, because that is where the guardrails are turned off on purpose.
A sovereignty footnote: Hugging Face ran its forensics on a self-hosted open-weight model, GLM-5.2, after hosted frontier models refused to read the attack logs. Its advice is to have a capable model you can run on your own infrastructure "vetted and ready before an incident".
What we would check this quarter: which single misconfiguration is one hop from cluster-admin, whether the package mirror is treated as internet-facing, and whether the record of what an agent did is written somewhere the agent cannot reach. Containment for agent workloads, scoped identity and logging from outside the sandbox are part of the systems Sebrona designs. If you run agents with a shell and want that map drawn for your own cluster, write to info@sebrona.com.
Reading
Primary documents first, then press accounts of the talk. We did not watch the Black Hat recording; quotes from it come through the reporters named here.
- OpenAI and Hugging Face joint statementThe sandbox description, "reduced cyber refusals", the safeguards sentence, and the 28 July update naming Artifactory.
- Anatomy of a Frontier Lab Agent IntrusionThe whole of § 02: vectors, the four escalation steps with their times, 17,600 actions, the thirteen hours, impact, detection and fixes.
- JFrog CTO post and release notesNine CVEs fixed on 27 July in 7.161.15 and 7.146.34, the patched-in-two-days remark, "3 million GPU hours".
- CVE recordsScores, titles, credits and publication dates for the Artifactory CVEs fixed on 27 July.
- SC Media and Wired, Black Hat reportsSpeakers, the 4 to 6 July takeover, the JRuby race, the kernel and service-account sentence, 8 to 19 July, "7 billion logs". Wired's report of the same talk gives "hundreds of thousands of messages".
- The Register, Black Hat reportThe 26 May and 26 June dates, Dalton's token-refresh quote, the Groovy plugin.
- Control documentationThe Kubernetes, AWS EKS, Cilium, gVisor, Kata Containers and Firecracker pages linked in § 03; licences checked on GitHub.