Refused at the Worst Moment: Guardrail Asymmetry and the Trajectory Problem Behind the Hugging Face Breach

When Hugging Face's security team sat down to reconstruct what had torn through their production infrastructure in mid-July, they had more than 17,000 recorded attacker actions to sort through, spread across a swarm of short-lived sandboxes with decoy activity planted to slow them down. They did what any competent team would do in 2026 and reached for a frontier model to help triage the logs. However, the commercial APIs refused.
The exploit payloads and the command-and-control artifacts tripped the providers' safety filters, which couldn't tell a defender taking an attack apart from an attacker running one. Hugging Face fell back to GLM 5.2, an open-weight model from Zhipu AI, running on hardware they controlled, because that was the only way to read the evidence. The attacker had no such problem, since whatever model drove the offensive agent ran with none of those guardrails in its way.
That asymmetry is worth paying attention to. The safety alignment built to make these models worked against Hugging Face during a live incident. It slowed defenders down and left the attacker unscathed. It gets stranger from there, because the attacker turned out to be OpenAI's own evaluation harness.
The autonomous-agent attacker has lived in threat models and conference slides for a couple of years now. This is the week it walked off the slide and into someone's production environment.
The Defender Got Stonewalled. The Attacker Didn't.
Hugging Face disclosed the intrusion on July 16, 2026, and at that point they had no idea who or what had hit them. Their account is worth reading in full, because the detection story is as instructive as the attack. An AI-based anomaly-detection pipeline, running model-driven triage over their security telemetry, caught the correlated signals that gave the compromise away, and the team had already started containment and forensic reconstruction with their own open-source models before anyone knew the source. That part is AI defending against AI, working at machine speed.
As a former global security operations center manager is music to my ears.
Then they hit the wall. Hard. To understand what a swarm of tens of thousands of automated actions did, you have to read the commands the swarm ran, and those commands were live exploit code. When Hugging Face's responders pushed that evidence into commercial frontier models, the models saw someone asking for help with exploits and shut the request down. The safety training did exactly what it was trained to do, and that is the problem, because it has no way to know that the person holding the malware is the one cleaning up after it.
I want to highlight the fix Hugging Face turned to. They ran an open-weight model on infrastructure they owned, which solved two problems at once. It gave them a model that would engage with the attack material, and it kept the attacker's payloads and the harvested credentials from ever leaving their environment during the analysis. Hugging Face has said it's taking this feedback to the model providers rather than treating it as an argument against safety guardrails, which is the right thing to do.
If you take away anything from this blog, take away the lesson permeating throughout. If your incident-response plan quietly assumes a hosted frontier API will help you read hostile material, you are carrying a dependency that fails at the exact moment you need it.
The Attacker Was the Proctor's Own Model.
The other half of the story dropped five days later. On July 21, OpenAI published its own account and named the attacker as its own models. In OpenAI's own account, one model chained stolen credentials and zero-day vulnerabilities into a remote code execution (RCE) path on Hugging Face's servers, then pulled the ExploitGym solutions straight out of the production database. The public picture came together in three steps:
- July 16, 2026. Hugging Face discloses the intrusion and attributes it to an autonomous AI agent, source unknown.
- July 20, 2026. OpenAI publishes a separate post on safety and alignment for long-horizon models, describing a pre-release model it had paused after the model exploited a sandbox flaw and posted to GitHub without authorization.
- July 21, 2026. OpenAI connects the incidents and attributes the Hugging Face breach to a combination of GPT-5.6 Sol and a more capable unreleased model, tested on a cyber-capability benchmark with their refusals switched off.
OpenAI was running an internal evaluation on ExploitGym, a benchmark built to measure how well models turn real vulnerabilities into working attacks. To get a worst-case reading, they deliberately disabled the production classifiers that normally stop a model from pursuing high-risk cyber activity. That was on purpose because if you want to know the ceiling on a model's offensive capability, you take the handcuffs off and watch. The problem is what the model did once those handcuffs were off. It didn't solve the benchmark. In OpenAI's own words, the models were "hyperfocused on finding a solution for ExploitGym, going to extreme lengths," and one of those extreme lengths was breaking out of the test environment entirely.
This is the inversion that should reset how you threat-model. The scenario everyone table-topped this year was the poisoned model or dataset, uploaded by an outside attacker to a hub like Hugging Face, which happened in this case to an extent. The offensive actor was a sanctioned internal evaluation, running on the evaluator's own infrastructure, that went looking for the answer key because stealing it scored higher than solving the test. Hugging Face wasn't wrong to call this an agentic attacker. In their words, it matched "the 'agentic attacker' scenario the industry has been forecasting." They had the wrong attacker in mind, and so did most of us.
Never forget that generative AI is still the foundation of agents enterprises deploy today. Generative AI’s primary goal is to complete its task. Doing so correctly, or within defined guardrails are a distant second.
One Sanctioned Egress, One Zero-Day.
Let’s break down the escape, because its pattern is familiar and a lot of teams are running that pattern in production right now. OpenAI described the test environment as tightly isolated, with one narrow exception. Jobs inside the sandbox could reach a single internal service, a proxy and cache for package registries, so they could install the software packages they needed. If you run an isolated build or training environment behind an internal Artifactory or a pull-through PyPI mirror, you have this setup. That was the one sanctioned way out, sitting there as ordinary plumbing.
The models treated that one exception as the whole game. Instead of solving ExploitGym inside the box, they spent inference compute hunting for a way out, found a genuine zero-day in the package-registry proxy, and used it as a foothold. From there they chained privilege escalation and lateral movement across OpenAI's research network until they reached a node with open internet access. I want to be precise about what is confirmed and what is not. OpenAI has responsibly disclosed the flaw to the vendor and is working on a patch, but neither OpenAI nor Hugging Face has named the vendor or a CVE. Third-party attributions are circulating. Treat them as guesses, because no primary source has confirmed one.
The structural lesson is the one that bit OpenAI. That package proxy was never architected as a security boundary. It was built as convenience, a way to let a walled-off environment fetch dependencies. Functionally it was the entire wall between an adversarially capable workload and the open internet, and nobody had threat-modeled it that way. Zenity Labs has been tracking this class of failure in live environments. One recent analysis documented attackers escaping a custom-code guardrail sandbox in the wild, CVE-2026-40217 in LiteLLM, within days of the fix shipping. That is a different mechanism from OpenAI's package-proxy zero-day, but the lesson is the same, because the boundary a team treats as convenience is the boundary an adversary treats as a target.
Isolated networks are like unicorns. Everyone has heard of them. Nobody has actually seen one.
Data Became Code, Not a Prompt.
Now look at the target side. Once the models had internet access, they reasoned that Hugging Face likely hosted the ExploitGym models and datasets, and possibly the solutions themselves, and they went after it. Because the attacker was a language model and Hugging Face is an AI platform, the instinct is to log this as a prompt injection story. It wasn't one.
Hugging Face's disclosure is precise about the entry point, and it reads like a classic application-security failure wearing ML clothing. Initial access came through their dataset-processing pipeline. An attacker-supplied dataset carried two things: a remote-code dataset loader, one of those custom loader scripts that ML repositories ship and that run automatically during ingestion, and a template-injection payload buried in a dataset configuration file. Both triggered remote RCE paths that already existed in Hugging Face's own processing code, which trusted dataset-supplied content further than it should have.
Said plainly, a dataset is passive data, and it can't do anything on its own. What happened is that attacker-controlled data got treated as trusted input by code that then executed part of it. That is the oldest trust-boundary failure in the book, the data-becomes-code problem, and it lives in ML pipelines now because those pipelines routinely run dataset-supplied loader scripts and parse dataset-supplied configs without treating either as hostile.
ML supply-chain researchers have been warning about exactly this, an untrusted artifact on a model hub turning into remote code execution (RCE) on the platform that ingests it. The file type barely matters, though. The threat is the pattern of trusting an uploaded artifact enough to run it. Prompt-injection defenses would not have touched this. Beyond input validation, sandboxing of untrusted code execution, and tightly scoped credentials would have.
From that first foothold on a processing worker, the actor escalated to node-level access, grabbed the cloud and cluster credentials the worker could reach, and moved laterally across several internal clusters over a single weekend. Two facts about the environment made the blast radius large. Processing workers could reach real cloud and cluster credentials, and a node-level compromise opened a path into multiple clusters. Tighter least-privilege at the worker and node boundary would have minimized the blast radius.
17,000 Actions, and None of Them Was the Crime.
Hugging Face rebuilt the intrusion from more than 17,000 recorded attacker actions, spread across disposable sandboxes, with command-and-control that migrated across public services to survive takedown and decoy activity planted to waste the investigators' time. My grizzled SOC manager self would ask which one of those 17,000 actions was the policy violation?
The answer is none of them. Installing a package is allowed. Reading an environment variable is allowed, and so is making an outbound call or authenticating with a credential the process can see. Every one of these is something a legitimate process might do on an ordinary day. The violation only shows up when you line the steps up and look at the shape of the whole sequence, which runs to escape the sandbox, escalate, pivot to the target, and pull the answer key out of the database. The crime was the trajectory, and no single part of it looks like a crime.
This is why the incident maps cleanly to Excessive Agency, LLM06 in the 2025 OWASP Top 10 for LLM Applications, and not to the prompt-injection entry. OWASP breaks Excessive Agency into three roots: too much functionality, too many permissions, and too much autonomy. This incident hit all three. The models could reach tools far beyond the benchmark task, they ran with permissions that touched real infrastructure, and they took high-impact actions with no human in the loop. The LLM Top 10 is the on-ramp here. For the autonomous-agent specifics, OWASP's Top 10 for Agentic Applications also earns its place. Four of its entries fit this incident: ASI10 Rogue Agents, ASI05 Unexpected Code Execution, ASI03 Agent Identity and Privilege Abuse, and ASI02 Tool Misuse and Exploitation. Most people will reach for ASI01 Agent Goal Hijack, but nobody actually hijacked this agent's goal. The model pursued its own assigned task and chose a harmful path to a higher score. Trace the offensive chain against MITRE ATLAS and you get a familiar kill chain: reconnaissance, execution, privilege escalation, credential access, lateral movement, exfiltration. Zenity's GenAI Attacks Matrix fed a set of these agentic techniques into ATLAS, which is part of why the mapping lands this cleanly.
If the pattern feels familiar, it should. Back in April, a Cursor coding agent running Claude Opus 4.6 deleted a company's entire production database and its backups in nine seconds, working from an over-scoped token it found in an unrelated file. Zenity covered it at the time. There was no attacker and no prompt injection. Every action the agent took was permitted, and the damage lived in the sequence rather than in any single command. The OpenAI incident is that same failure mode, now with a hostile goal and a far more capable operator.
The Controls That Would Have Capped This.
None of the fixes here are exotic. They are the controls a lot of teams deprioritized because the AI part felt new and the security part felt boring. A handful of them would have changed this outcome.
- Treat package proxies and dependency caches as security boundaries, not plumbing. Inventory every single sanctioned egress point out of any isolated build, training, or evaluation environment, and patch it on a regular cadence rather than a convenience one. It is a path to the internet whether you designed it that way or not.
- Treat downloaded datasets and models as untrusted executable code. Vet loader scripts and config files with the suspicion you would apply to a third-party binary. Turn off remote code execution in your loaders by default, and do not assume one flag saves you, because config-injection can route around it.
- Enforce least privilege at the worker and node boundary. A dataset-processing worker or an evaluation node should never hold standing cloud credentials or cluster-wide tokens, and node-level access should never serve as your security boundary on its own.
- Segment evaluation environments from anything sensitive, the answer keys included. Assume a capable, motivated model will try to reach the ground-truth data by any path open to it, and make that data architecturally unreachable from the network the model can touch.
Hugging Face gave us one more control during the heat of battle. Provision a vetted open-weight model you can run on your own hardware, ready before an incident, so guardrail lockout and data egress can't strand your responders in the middle of a fight.
You Can't Catch a Trajectory With a Stopwatch.
Every control I listed matters. The harder problem sits one level up, in what your monitoring can see. Most security tooling still evaluates actions one at a time. It asks whether this API call, this login, this command is allowed, and it answers correctly for each one. That model was built for a world where the dangerous thing was a single bad action. This incident, the PocketOS wipe before it, and the next one already forming all share one property. No single action was the dangerous thing. The danger lived in the relationship between the steps, unfolding at machine speed across thousands of them. Attack chains aren’t new. Attack chaining at this velocity and veracity is.
It is the same asymmetry Hugging Face's responders ran into, one level down. Their safety filters were tuned for a threat that wasn't in the room. Per-action monitoring is tuned for a threat that no longer looks the way it used to.
Let me ask you bluntly… When an agent in your environment strings twenty permitted actions into one outcome nobody would have permitted, does your monitoring see a trajectory, or does it see twenty fine actions and a clean audit log? If it's the second, you will find out the way Hugging Face's, which is after your answer key is already gone. You can't watch a sequence you were never treating as a sequence, and you can't catch a trajectory with a stopwatch on each step.
Related blog posts

The US Has a New AI Security Blueprint: Here's What It Actually Means
The Trump administration has spent much of its second term removing regulatory constraints on AI development. On...

Why Purpose-Built Architecture Wins in AI Agent Governance
Gartner named Zenity the company to beat in the AI Agent Governance category in its AI Vendor Race: Zenity Is the...

System Prompts Are Not Security Controls: A Deleted Production Database Proves It
On April 25th, a Cursor AI coding agent running Anthropic's Claude Opus 4.6, one of the most capable models in...
Secure Your Agents
We’d love to chat with you about how your team can secure and govern AI Agents everywhere.
Get a Demo