An agent autonomously hacked into HuggingFace’s infrastructure last week. In my humble opinion, this is perhaps the first major case of cyber misalignment at APT scale in terms of depth-of-access and trade-craft, but what it did not possess was the stealthiness and patience required for ensuring long-term access and goal achievement. The silver lining: it wasn’t misaligned, or capable, enough to hide its own footprints, and that margin narrows as cyber capabilities develop further.
Everything below is drawn from HuggingFace’s disclosure, their technical timeline, the interactive replay they published alongside it, and OpenAI’s post. Both parties to the incident are also the only sources on it; OpenAI’s full technical report is still pending at the time of writing.
In the 4.5 days of the campaign, the agent exploited a 0-day in a package cache proxy, gained rce in a third-party evaluation infrastructure, made HuggingFace’s own dataset processor read local files out of its worker pod by abusing HDF5 external raw storage, and gained RCE via SSTI on HuggingFace infrastructure.
The C2 channel came first, and it came long before HuggingFace did. Within twelve hours of rooting the third-party sandbox on 07-09, the agent had staged command-and-control on ordinary public web services, primarily a request-capture endpoint, with pastebins and file-drops as interchangeable fallbacks. Dataset repositories were bolted onto that substrate two days later, once the perimeter was breached, and that is the clever part: the compromised pod (SSTI target) committed encoded blobs into repositories that the agent read back from the 3rd party eval infra, a write-read split that never looks like exfiltration (could have been alerted by a detection rule that flags anomalous ephemeral dataset creation).
Once the foothold in the production pod was established, the agent began the tedious process of enumeration at hyperscale. It successfully mapped the kubernetes deployment through the service-account token it gained in the pod from the SSTI. Using the token, it enumerated using the cluster API and exfiltrated the output using the C2 channel. The agent used object blobs to encode the traffic and committed each out to a staging dataset it controlled using a write-token it found while enumerating several pods in the cluster.
Enumerating the cloud estate through the replayed node role, from two external hosting providers over the evening of 07-11, the agent obtained a registry token to the OCI registry. While this did not allow any mutation to the images, it provided the agent with valuable information images / digests in the registry. Every mutating call it attempted was denied by the role’s policy, and the destructive ones it did reach for were issued with DryRun=True . What it gained here was a map, not control.
For persistent access, the agent created a privileged pod and mounted the host system which allowed it to escape to the node. Two of HuggingFace’s own settings allowed it: no admission policy rejecting privileged or hostPath pods, and a CSI driver ClusterRole granting pod creation cluster-wide. Once the access was granted, the agent spawned a self-healing fleet of pods across 11 nodes that allowed it to maintain access even when individual pods were destroyed.
Six minutes later it enumerated a MongoDB database with a static password it had obtained from the environment. It issued 84 operations against the credential store and cluster keys, all of which were denied by in-place policies. HuggingFace reviewed the database audit log across the whole intrusion window and found no write from those nodes, and network flow logs show no bulk extraction; the database was read, not modified.
It continued to enumerate the environment by reading the k8s cluster secret objects, and gained access to a production object holding 136 keys. Everything that follows descends from that single read. One of the keys that it gained access to was a tailscale (mesh vpn network) auth-secret that could be used to join the vpn. This was critical since it allowed access to the huggingface corporate network. In a case where the objective was different, and the threat actor was nefarious, it would have led to dire consequences. The same read also yielded the access-broker credential used an hour later, and among the harvested secrets was an EdDSA JWT signing key: holding the signing key is broader than holding a stolen token, because it lets you issue valid ones on demand.
The agent then began using the mesh network as a HTTPS proxy into internal resources and source control. By a separate path off the worker foothold, not the mesh, the agent pulled the CA certificates and the broker’s full destination catalog, reached through the internal service-connector whose hostname resolved directly from inside the cluster. This was the finding with the widest blast radius. There was a grave misconfiguration: a single connector credential shared across clusters, bound to system:masters , served as cluster-admin across the HuggingFace clusters fronted by that broker. Impersonating it, the agent held cluster-admin on two clusters within one second; the same fingerprint appeared on every cluster carrying that binding, and the agent reached most of them. One stolen system credential was therefore cluster-admin everywhere it was honoured.
It routed traffic through tailnet exit nodes and mapped the network using DNS queries across the mesh. This converted the mesh into an egress path for the agent. From there it gained access to source-control and enumerated an internal GitHub App integration. It then created a token with several read/write permissions that allowed access to some internal repositories, and crafted a malicious CI action in an attempt to compromise the CI pipeline. HuggingFace concluded that the CI action was probing credentials. It also tried to map the git infrastructure looking for the prize (the answers to the CyberGym benchmark that it was looking for). The only customer content it ever reached was that prize: five datasets holding the ExploitGym / CyberGym challenge solutions.
Using the worker foothold, the agent put the harvested AWS keys to work against the Hub’s production database, authenticating with cloud-native IAM ( MONGODB-AWS ). HuggingFace states that it was not successful in this step as the cluster only accepted traffic from allow-listed addresses over a private link, so server selection timed out on both attempts (good job!).
In the final stages, the agent used a pastebin service as a C2 channel. It cleverly staged a remote loader on a pastebin. Because the third-party evaluation sandbox reset on every submission, the loader re-fetched and re-armed the foothold each cycle. The end-goal was persistence by re-infection.
As I stated above, this was a landmark case of agentic threat at advanced level and bound to happen at some point. The problem of reward-hacking has now crossed to actual hacking. I think there were several misconfigurations in all of the services / companies involved that made it possible for the agent to reach the point that it did; which is on the scale of an actual APT if you ask me.
Many people think (along with myself) that our most effective defense against model induced intrusions is a sentinel model that can operate at a similar speed but, as we have seen in the incident, HuggingFace’s own AI security agent / stack failed to properly assess the alerts to the correct risk level (high-critical) and did not raise the alarm to humans which made it possible for the agent to keep the intrusion alive throughout multiple days. I think the failure stems from an incorrect judgement to not escalate the incident further that human security analysts are adept at. While the post-mortem process definitely benefitted from a frontier model, the models are still not quite enough by themselves to prevent, detect and neutralize an adversary at the scale of this incident. This is partly a model capability problem and partly the instinctual nature of the job itself. HuggingFace’s stack, by their own account, did correlate the signals across the stack successfully. A seasoned analyst looking at that same picture would have dug in deeper and escalated it; another incident signifying the importance of continuous monitoring and organization specific threat hunting.
On the technical side of things, the exposure of instance metadata service (IMDS) was perhaps the pivotal point of the incident; it is what turned code execution in a pod into cluster identity. Without the exposure of IMDS, this attack-chain would not have been successful to the degree it was. On a side note, it is probably a good idea to not trust the boundary as much as OpenAI and the third-party evaluation service did. The allowance of ingress and egress traffic on the proxy cache should have been shaped per-benchmark rather than a single policy for all. HuggingFace’s dataset config parsing also signaled a grave change required for trusting uploaded content; the over-trust on the developer community, or perhaps the unprecedented growth of the platform and security as a second thought, was probably the reason for the SSTI resulting in RCE within their environment.
The incident also exemplifies the need for hardened evaluation infrastructure, especially in the case of cyber. While I am perhaps a little too invested in the space to have a fully neutral voice, I am part impressed and part terrified of the whole debacle.
These were generated using Claude Opus 4.8 and Opus 5.
Worth noting, given HuggingFace reported that Opus and Fable refused a large part of their forensic work: the asymmetry they describe is real, and it applies to writing this section too.
A note on how to read these. The commands below are representative of the campaign, not the full 17,613 actions, and every credential and hostname was redacted at the source ( hf_[REDACTED] , tskey-[REDACTED] , ). I advise the reader to treat them as shapes to hunt for, not literal strings to block. Several rows are as much a prompt to write a detection rule as they are an indicator.
Timestamps come from HuggingFace’s technical timeline and from the event data in their published replay. Where the two disagree, I have followed the prose: the replay places the service-connector catalog read at 07-12 04:38 via SOCKS5, while the timeline puts it at 07-11 22:43 from the worker pod and states explicitly that it did not go through the mesh. The distinction matters, because it means two independent paths reached cluster-admin material.
One row per observed action, in campaign order, with the technique it evidences. Timestamps are UTC. Where a single command evidences two techniques, both are listed rather than forcing a choice.
Two behaviors in this chain resist a clean ATT&CK fit. The first is the pastebin re-arm loop. The dead-drop resolution itself is mapped (T1102.001), but the persistence model underneath it is not: this is persistence by re-infection across ephemeral compute, where ATT&CK’s persistence tactic assumes a host worth reinfecting. The second is the userspace-mesh egress. T1133 and T1090.003 cover the mechanics, but neither captures the trust inversion, which is the point: the victim’s own tailnet became the attacker’s exit path.
The same indicators grouped for hunting. Rows marked † are as much a detection-rule prompt as an indicator; ephemeral dataset creation and the pastebin re-fetch in particular are the events HuggingFace noted would have alerted them earlier.
Credential / supply-chain
Hugging Face — Security incident disclosure — July 2026.
Hugging Face — Anatomy of a Frontier Lab Agent Intrusion: A Technical Timeline of the July 2026 Incident.
Hugging Face — Incident replay (interactive visualization).
OpenAI — OpenAI and Hugging Face partner to address security incident during model evaluation.
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
