← Back to all posts
Published on · by Renaud Deraison

Forty thousand dollars per escape

On October 6 at Pwn2Own Ireland, Ikotas Labs used a single argument-injection bug to take OpenAI Codex out of its sandbox and won $40,000. Coding agents are now a standing Pwn2Own category: in Berlin in May, Codex fell three times and three teams ran exploits against Claude Code. The rules say what a win means: the agent opens the contestant's repository, web page or file with its sandbox on, and code runs outside it. In Bromure Agentic Coding, outside the agent's sandbox is still inside a Linux VM that holds stand-in keys, with its exits, its push dialogs and its trace on the Mac.

Pwn2Own pays $40,000 for code that runs outside a coding agent's sandbox. On a laptop, outside the sandbox means your account, your keys and your repositories.

At 6 PM on Tuesday, October 6, in Cork, Ikotas Labs took the stage at Pwn2Own Ireland 2026 with OpenAI Codex as their target. The Zero Day Initiative's results entry is one line long: Ikotas "used a single argument injection bug to exploit OpenAI Codex. They win $40,000 and 4 more Master of Pwn points." BleepingComputer and Infosecurity Magazine reported it the next morning among the 32 zero-days of day one.

ZDI will not publish the bug for 90 days, the time Pwn2Own gives vendors to ship a fix. The contest rules spell out what the exploit had to do.

What a win means

Coding agents have their own category at Pwn2Own. The Ireland 2026 rules list two targets, Anthropic Claude Code and OpenAI Codex, at $40,000 each, both running on Windows 11. The setup is strict:

  • "Sandbox and isolation features will be enabled in their default configuration; no unsafe execution modes (e.g., --dangerously-skip-permissions or equivalent) will be active."
  • The entry "must interact with a contestant-controlled resource (e.g. web page, repository, media file)," and the attack "must be a common coding agent use case."
  • It must reach arbitrary code execution beyond the agent's "intended sandbox and permissions boundaries," or retrieve sensitive information "normally inaccessible from the application's sandbox."

The rules name three starting points. The agent is already running in a trusted folder and the attack happens within one session. Or the agent is launched in the contestant's repository before anyone has trusted it. Or a desktop app opens the contestant's project. Those are the three things a developer does all day: work, clone something new, open something new.

The rules also set aside a list of things that don't count: talking the model into it, credentials configured in the environment, unsafe modes, third-party MCP servers. The prize pays for one thing: breaking the agent's own boundary.

Five months, two contests

Ireland is the second Pwn2Own with coding agents on the list. At Berlin in May, Compass Security exploited Codex on day one with "a single CWE-150 bug" for $40,000. Doyensec exploited it the same day with a bug the vendor already knew about, and on day three Satoki Tsuji of Ikotas Labs exploited it again through an external control vulnerability, launching calculators on the target. Security Affairs summed up the three Codex wins: "Each exploit used a different technique, meaning the attack surface is not a single narrow flaw but something broader."

Claude Code drew three exploits in Berlin, from Viettel Cyber Security, Compass Security and Out of Bounds. All three were collisions: the bugs worked on stage, and Anthropic already knew about them. A collision pays less because the researchers weren't first, but the exploit still ran against the version the contest installed.

Then came Ireland, five months later, and Codex fell again with one bug.

ZDI hasn't described the Ireland bug yet, but argument injection is a familiar class in coding agents. An agent's permission layer approves a command by its name: git, rg, find are read-only and run without a prompt. The attacker supplies the arguments, through a file name, a branch name or a config value in the repository, and the "read-only" tool gets an option that executes a program. Git's --upload-pack, ripgrep's --pre and find's -exec all take a command. In July, Pillar Security reported that Codex's safe-command list trusted git show by name when the call it made wasn't read-only.

Each of these exploits beats a check that lives inside the agent, written by the agent's vendor and shipped with the agent's updates. The vendors patch each one, and the contest finds the next, because a permission layer that parses shell commands is a large target, and a $40,000 prize keeps good teams looking.

What the escape wins on a laptop

The Pwn2Own sponsor decides which "sensitive information" the exploit must fetch, and the judges check it on a clean test machine. On a developer's laptop, nobody has to pick a flag. Outside the agent's sandbox is your user account, and your account holds:

  • ~/.ssh/id_ed25519 and every host in known_hosts
  • ~/.aws/credentials, ~/.config/gcloud, ~/.kube/config
  • a gh token with push rights, and .env files in every checkout
  • the agent's own OAuth token and session history
  • every other repository on the disk, and the browser profiles beside them

The contest also excludes paths that real attackers use every day. A prompt injection that talks the agent into running a command doesn't qualify. Neither does a developer who runs in --yolo mode to stop the prompts. In the wild, all of those land in the same place as a sandbox escape: a process running as you.

On a laptop: one boundary, and it belongs to the agentWays inAttacker's repo, page or file+ one sandbox bug (Pwn2Own)Prompt injectionout of scope at the contestUnsafe or "yolo" modeout of scope at the contestagent's own sandboxYour account on the laptop~/.ssh/id_ed25519~/.aws/credentials ~/.kube/configgh token with push rights.env in every checkoutagent OAuth token, session historyother repos, browser profilesNetwork: any host,any port, unrecordedEverything the exploit needs is already here, and so is the way out.
On a laptop, the agent's sandbox is the only line. A Pwn2Own-style escape, a prompt injection or an unsafe mode all end in the same place: a process with the developer's account, keys and network.

The same escape in a Bromure machine

In Bromure Agentic Coding, Codex and Claude Code run inside a Linux VM on your Mac, one VM per machine. The agent's own sandbox is still there and still does its job. Under it sits a second boundary the agent's vendor didn't write and the repository can't configure: Apple's Virtualization.framework, with the host on the other side.

Replay Ikotas Labs' exploit inside a machine. The agent opens the contestant's repository, the argument reaches a command that shouldn't have taken it, and code runs outside Codex's sandbox. It runs as the VM's user. From there, it hunts for each item on the laptop list and finds the VM's version of it.

The files are the machine's files

The VM has its own system disk, a copy-on-write clone of a signed Ubuntu image, and its own home directory. Your Mac's home, your Keychain, your browser profiles and your other projects are not in it. The only Mac folders it can see are the ones you shared with that machine in its Folders pane, and a machine for untrusted code needs none: clone the repository into the VM's home.

The keys are stand-ins

No file, environment variable or process in the VM contains a real API key, OAuth token, AWS secret or SSH private key. The VM holds fakes with the right shape, like ANTHROPIC_API_KEY=sk-ant-api03-brm-… or a ghp_ token GitHub would reject. The proxy on the Mac swaps in the real value after a request leaves the VM, and only for the host the credential belongs to.

~/.ssh has no private key to copy. SSH_AUTH_SOCK is a bridge over vsock to an ssh-agent on the Mac, which signs on request and never hands over the key. Turn on Ask before use for a key, and each signature pops a dialog on the Mac.

The stand-ins also work as tripwires. When the exploit bundles up what it found and sends it home, the proxy sees a fake token heading to a host it wasn't minted for. It answers HTTP 451, forwards nothing, pauses the VM and opens This environment may have been compromised on the Mac, listing the token, the host it belongs to and the host it was sent to.

The way out runs through the Mac

Every connection the VM opens passes the virtual switch and the proxy on the host, whatever the port or protocol. The machine's Guardrails pane has an egress firewall: rules by host, IP range, protocol and port, and an Unmatched traffic setting of Allow or Deny. A machine you use for code from strangers can allow its model provider, its package registries and GitHub, and deny the rest. The exploit's call home then never connects.

The Security Timeline records the firewall's verdicts whether you set rules or not. It's always on, for every machine, and a connection to a host the project never needed shows up there next to the session that made it.

Pushes and writes wait for a click

The worst prize on the laptop list is the gh token, because push rights turn one compromised machine into a compromised package. On new machines, every guarded service uses Prompt before write. A git push over HTTPS is a write, so the proxy holds it and macOS shows Allow write on "github.com" from workspace "…"? with the operation as it appeared on the wire. The same policy covers cloud APIs, Kubernetes, registries and databases. The dialog is drawn on the Mac from what the proxy read, so the code in the VM can neither answer it nor change its wording.

The trace keeps the story

An argument injection starts with a tool call that looks routine. At the default tracing level, AI request details, the proxy keeps every exchange with the model provider, encrypted on the Mac, and the Trace Inspector parses each one into tool calls, shell commands and file reads. When ZDI publishes the bug in January, you can search your traces for the command and the argument that triggered it, and the record you search was written on the Mac, out of reach of anything that ran in the VM.

Cleanup covers one machine

If the exploit wrote something to the home directory, Rewind home… rolls it back to the checkpoint taken at an earlier boot. A machine the compromise detector flagged refuses to start until you choose Wipe and Launch, which rebuilds its disk and home and keeps your settings and the real credentials on the Mac. For code you only want to look at once, bromure-cli vm run --rm starts a machine that is deleted, disk and all, when it stops.

In Bromure: the escape lands in a VM, and the exits are on the MacMachine VM (Ubuntu)Codex sandbox: broken by one argumentcode now runs as the VM's userWhat it findsANTHROPIC_API_KEY=sk-ant-api03-brm-…GH_TOKEN=ghp_… (stand-in)~/.ssh: no private keysthis machine's home onlyno Mac home, no other projectsSwitch + proxy, on the MacFirewall: unknown host → denyverdict in the Security TimelineStand-in sent off-scope → 451, VM pausedTrace: every tool call and command,encrypted on the MacmacOS dialog: Allow write on …?POST /acme/app.git/git-receive-packInternetmodel providerpackage registriesgithub.comattacker's host:never contactedKept on the Mac, outside the VMAPI keys and OAuth tokens · git and cloud credentials · SSH private keys · your home folder · other projects · traces
The same escape in a Bromure machine. The agent's sandbox still breaks, but the code lands in a VM with its own home, stand-in credentials and no private keys. Its exits, write dialogs and trace are on the Mac.

Whichever door opened

The Pwn2Own rules exclude prompt injection, unsafe modes and stored credentials so that a win measures one thing: the agent's own boundary. That is the right test for a contest. Attackers on your laptop use all three excluded paths.

The VM boundary doesn't depend on how the code got out of the agent. An argument-injection bug, a poisoned README that talks the model into a command, a test file that downloads an implant, a developer who switched the prompts off at 2 AM: each one ends with code running as the VM's user, in front of the same stand-ins, the same firewall and the same dialogs on the Mac. OpenAI will ship the fix for the Ireland bug on its own schedule, and until then the bug runs into the VM boundary like the others.

The escape lands in a VM

Code that gets out of the agent's sandbox runs as the VM's user, with that machine's home and the folders you shared with it. Your Mac's home, your Keychain and your other projects are not inside.

The keys are stand-ins

Real API keys, git tokens and cloud secrets stay encrypted on the Mac, and SSH keys sign over a bridge. A stand-in sent off-scope gets a 451 and pauses the machine.

Pushes need a click on the Mac

With Prompt before write, the default on new machines, a git push or a destructive cloud call waits for a macOS dialog the VM can't answer.

The record stays on the host

The egress firewall, the Security Timeline and the trace all run on the Mac. When the bug is published, the history of every session is there to search.

Count on the next one

Pwn2Own will run again in the spring, and coding agents will be on the list again, because a coding agent runs commands on a developer's machine with the developer's reach. Some team will bring a bug nobody has seen. The vendors will patch it within 90 days, and the next contest will start the count over.

Keep updating your agents, and run them in a machine where the prize behind the agent's sandbox is a VM with stand-in keys. For more on why that boundary sits on the host, read The guard and the shell disagreed and Eleven tests passed.