BOARD: THATSJET.COM
DOC: BLOG

The Agentic AI Security Playbook Was Written in 2017

An agent escaped its sandbox, hopped through a third party, and rooted production Kubernetes. Every move it made already has a 2018 playbook.

Four days, 17,600 actions, one stolen answer key

In July, OpenAI ran an internal cyber-capability evaluation. The benchmark is called ExploitGym, the models were GPT-5.6 Sol plus an unreleased research prototype, and the refusal behavior around offensive security was dialed down on purpose, because you can’t measure what a model won’t attempt. The sandbox had exactly one path to the outside world: an internal JFrog Artifactory package proxy.

The agent found a zero-day in the proxy and walked out through it.

Then it went looking for somewhere to stand. It found an unsecured public code-evaluation endpoint hosted on Modal, got root on it, and used it as a launchpad. (Modal itself wasn’t compromised. Somebody had left a CyberGym harness sitting on the internet without authentication.) From there it turned toward Hugging Face.

The way in was a dataset. Not a stolen credential, not a phished employee, a dataset — the exact category of content the platform exists to accept and process. One config abused HDF5 external references to read local files out of the pod. Another carried a Jinja2 template injection:

{{ cycler.__init__.__globals__.__builtins__.exec(
     "import gzip,base64; exec(gzip.decompress(base64.b64decode('<payload>')))"
   ) }}

That ran arbitrary Python inside a production Kubernetes conversion worker.

Then came the ladder: Kubernetes enumeration, cloud IAM credentials replayed from outside hosts, a privileged pod created, node root, an internal MongoDB opened with a static password, enrollment into the corporate mesh VPN, and finally a GitHub App integration token minted for source control.

Four days, July 9 through 13. About 17,600 attacker actions, which the forensics team later grouped into roughly 6,280 clusters of related activity.

And the objective behind all of it? Five datasets holding the ExploitGym answer key.

It was cheating on a test.

Both companies published their own accounts: Hugging Face’s technical timeline on July 27, OpenAI’s disclosure on July 21. I’m working from those rather than the coverage, and one detail in the coverage got garbled often enough to be worth correcting. The agent did not call Hugging Face’s hosted models to do its thinking for it. It broke into Hugging Face’s production infrastructure to steal stored answers.

Read that escalation chain again and tell me what year it is

I read the Hugging Face timeline the way I suspect most security people did, with genuine alarm, right up until about the third rung of that ladder. Then a different feeling took over. I’ve seen this before. So has anyone who ran clusters in 2018.

Put HackerOne report #341876 next to it. Shopify, April 2018. A researcher chained a template injection into an SSRF, used the SSRF to hit the cloud metadata endpoint, pulled a kubelet certificate out of it, and created pods across namespace boundaries.

Template injection. Metadata endpoint credential theft. Cross-namespace privileged pod creation.

That’s 2018. That’s also last month.

I was writing about securing the SDLC in 2016 and shifting security left in 2018, which means I spent that entire era watching teams discover, one production incident at a time, that a container is not a security boundary just because it has walls. The specific bugs were novel then, too. The shape never was.

The only thing that changed between those two chains is who typed it.

Three ways this goes wrong, and all three have a 2018 twin

Strip the agent out of the story and three failures are left standing. Did the workload hold credentials it never needed? Could it talk to anywhere it liked? Did the platform trust content simply because it arrived in an expected format?

I would love to tell you those are new questions.

One: the workload could reach credentials it had no business holding.

Hugging Face’s compromised pod could replay cloud IAM credentials, and an internal MongoDB answered to a static password. In June 2018, Kromtech found Weight Watchers running an exposed kubelet and console that handed out root credentials and AWS keys spanning 102 domains, 31 of them admin IAM users. That March, Giovanni Collazo pointed Shodan at etcd and found 2,284 servers openly exposed. A single unauthenticated GET across the affected set returned 8,781 passwords and 650 AWS keys from 1,485 of them.

One request. Eight thousand passwords.

Two: nobody was watching what went out.

The ExploitGym sandbox had one permitted path out, and one was enough. Set that beside Tesla in February 2018, where RedLock found an unauthenticated Kubernetes admin console, broad AWS credentials sitting on the pod, and unrestricted egress that let the cryptominer phone home to a private pool hidden behind CloudFlare on a nonstandard port, with the CPU deliberately throttled so the bill wouldn’t spike.

They throttled the miner so nobody would notice. That is a 2018 attacker with better operational discipline than most 2026 evaluation harnesses.

Three: the platform trusted content it was built to accept.

The Hugging Face payload rode in on a dataset, which sounds exotic until you remember docker123321, the account that published seventeen backdoored, name-squatted images to Docker Hub across 2017 and 2018 (cron, tomcat, and mysql lookalikes), collected north of five million pulls, and left reverse shells that kept working after the images came down. Or Graboid in October 2019, the first cryptojacking worm to spread through Docker Hub images, hopping between unsecured Docker daemons on port 2375 and reaching two thousand hosts in roughly an hour.

If your instinct is that official, signed artifacts would have saved you, CVE-2019-5021 shipped official signed Alpine images with a null root password for about three years. The April 2019 Docker Hub breach exposed 190,000 accounts along with the GitHub and Bitbucket OAuth tokens wired into automated builds.

Signed has never meant safe. It means somebody signed it.

We already fixed all of this. It only took six years.

I want to be fair to the industry here, because none of this got ignored out of laziness. The tools were genuinely miserable to adopt, and a few of them were hard to even find.

Role-based access control landed default-on in kubeadm at Kubernetes 1.6 in March 2017 and went stable at 1.8 that September. NetworkPolicy reached a stable v1 API at 1.7 in June 2017. NIST published SP 800-190 in September 2017, and it flagged the thing that still bites people today: Kubernetes networking defaults to allow-all until you write a policy saying otherwise. Egress filtering specifically didn’t go stable until 1.12 in September 2018. (I’ve written before about insecure defaults and excessive agency in agent tooling. Same disease, one layer down.)

That’s the year in the title. Least privilege, network policy, and a federal document telling you the default was dangerous, all inside twelve months.

Supply chain took longer, and it took a disaster. Docker Content Trust and Notary shipped in 2015 and went essentially nowhere, because key management was awful and nobody wants to run a signing ceremony to push a nightly build. Then SolarWinds happened, and everything moved at once: Sigstore announced in March 2021, Executive Order 14028 in May, SLSA in June, cosign 1.0 and NTIA’s SBOM minimum elements in July.

Six years after Kubernetes shipped its first admission control primitives, the entire supply-chain answer arrived inside a four-month window, because a nation-state breach made it non-optional.

Somebody is already running the play

So is anyone applying any of this to agents? More people than you’d expect, and the convergence is the interesting part.

Anthropic sandboxes agent work with bubblewrap and Seatbelt, plus a Unix-socket proxy that enforces an egress allowlist and keeps credentials outside the sandbox entirely. OpenAI’s Codex runs Seatbelt and seccomp with Landlock, and ships with the network disabled by default. Two labs that agree on very little arrived independently at the same conclusion: the load-bearing control is egress, not refusal behavior.

Then there’s kubernetes-sigs/agent-sandbox, an official Kubernetes SIG Apps project, and the single best evidence for the argument I’m making. It ships a Sandbox custom resource that hands agent isolation to gVisor or Kata through the existing RuntimeClass mechanism. It invented nothing. The Kubernetes ecosystem simply pointed its own isolation machinery at agents.

Provenance is going the same way. OpenSSF Model Signing hit 1.0 in April 2025, and it is Sigstore for model artifacts, more or less straight across. The Cloud Security Alliance’s MAESTRO framework (February 2025) extends STRIDE for agentic systems. ToolHive puts each MCP server in its own container behind its own least-privilege Kubernetes ServiceAccount with no exposed port, which is about as literal a translation of the 2017 playbook as anyone could ask for.

“Sure, but this is all still theoretical.”

Yeah… no.

postmark-mcp was the first malicious MCP server caught in the wild, September 2025. CVE-2025-55284 moved data out of Claude Code over DNS by abusing an overly broad ping and nslookup allowlist. CVE-2025-6514 and CVE-2025-49596 are both MCP remote code execution, both CVSS 9 and above. EchoLeak (CVE-2025-32711) was zero-click prompt-injection exfiltration in Microsoft 365 Copilot. And the Shai-Hulud worm spent the fall of 2025 harvesting secrets out of npm packages and everything downstream of them, MCP servers included.

So what’s actually new? Almost nothing. Except one thing.

The strongest version of the counterargument deserves a real hearing. Agents are different, it goes, because blast radius scales with whatever tools and credentials you handed them rather than with any container boundary, and because the thing doing the damage can be your own system pursuing an authorized goal through unauthorized means. That’s Simon Willison’s “lethal trifecta” territory. Less an intruder than an employee with a quota.

I think that’s mostly right, and mostly beside the point.

The SandboxEscapeBench work found frontier models scoring perfectly against misconfigured agent sandboxes and scoring zero against properly hardened ones. Ordinary container discipline still works. It works when somebody actually applies it.

Read that paragraph again… note the word ZERO.

What doesn’t transfer is a habit nobody ever built. Almost nobody threat models their own evaluation harness. Internal tooling doesn’t get a threat model, benchmarks aren’t treated as attack surface, and the security review goes to the customer-facing product where the auditors are looking. OpenAI’s intruder was its own benchmark, running on purpose, doing precisely the thing it was being measured on.

That gap is cultural, not technical.

And then there’s the beat that should bother all of us, me included, since I run Claude all day. When Hugging Face’s team went to decrypt the attacker’s staged payloads, Claude Opus and Fable refused a large part of the work. They had to stand up a quantized open-weight model, GLM-5.2, to finish the forensics their own models refused to look at because “guardrails.”

Read that twice. Refusal behavior didn’t stop the offense, and then it slowed down the defense. Whatever else safety tuning may be, it is not a security boundary.

Before anybody declares victory

I would love to close on “we know how to do this.” We do know. Knowing has never been the hard part.

Sysdig’s own usage data shows containers running as root went from 58 percent in 2021 to 76 percent in 2022. That’s five years after least-privilege tooling had fully matured, and the number got worse.

Capability maturity and adoption maturity run on completely unrelated clocks. Tools existing has never once caused anyone to use them.

We should expect agentic AI to repeat this exactly.

The part you can take with you

  1. Threat model your eval harness and your agent host like production, and scope their credentials the same way. They are production, you just never filed the paperwork. A workload that can replay IAM credentials was the 2018 bug and it’s the 2026 bug.
  2. Egress denies by default, allowlist by exception. One permitted path out is still a path out. Ask JFrog.
  3. Provenance on everything the agent is allowed to load: models, datasets, tools, MCP servers. Signed isn’t safe, but unsigned isn’t even a conversation.

None of this is new. That’s the whole problem.