Skip to content

Build1 publisher3 min readPublished

Untrusted JavaScript found Codex's auth token in the shared V8 heap and ran a host command

Researchers escaped the OpenAI Codex sandbox twice, writing outside the workspace in workspace-write mode and launching a host application from read-only mode. Both bugs were fixed within eight days of being reported.

The Engineer · Build desk

Illustration accompanying Untrusted JavaScript found Codex's auth token in the shared V8 heap and ran a host command

What happened

  • The second technique took a V8 heap snapshot from the untrusted context of the node_repl MCP server and tested UUID-shaped strings against the token the trusted context sends to the native Rust parent.
  • In read-only mode, asking a question about a repository was enough to launch a host-side application with no approval prompt and nothing displayed on screen.
  • Both issues were patched within eight days of reporting, and no exploitation in real-world attacks has been reported.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint Picking the stricter of the two modes did not change the outcome, so an operator choosing workspace-write or read-only for an untrusted repository is setting a convenience level and getting containment from somewhere else.
  • exposure A credential that leaks inside the sandbox reaches a Docker daemon socket, according to the researchers. That is the container machinery an operator would use to build the outer boundary, and it sits within reach of the code being isolated.
  • decision Detection depends on file evidence: node_repl entries in ~/.codex/config.toml, symlinks from the workspace into the home directory, and unexpected .zshrc changes are the artifacts the report gives administrators.
  • precedent Any in-process JavaScript sandbox that authenticates to a privileged parent with a secret living in the shared heap has this shape, and agent plugins built that way should be assumed bypassable until the credential leaves the isolate.

`apply_patch` has to create files that do not exist yet, so it cannot inspect the target before deciding whether a write is allowed. At the time it decided from the parent directory of each path in the patch [5]. The researchers named `/tmp` as a file target in a no-op entry; the write failed because `/tmp` is a directory, and its parent, `/`, was added to the allowed write scope anyway [6].

The rest is ordinary filesystem work. A symbolic link inside the workspace pointed at the home directory, the same patch appended a line to `$HOME/.zshrc`, and the appended command runs on the host at the next terminal launch [7]. A regular shell command writing to `$HOME` in workspace-write mode is blocked [4].

Heapjack is the better piece of research. Codex Desktop wrote `[mcp_servers.node_repl]` into the global `~/.codex/config.toml`, which also exposed the server to the CLI [8]. That server runs one Node process inside the sandbox holding two V8 `vm` contexts, trusted and untrusted, on a single isolate and heap [9]. The trusted context authenticates to the native Rust parent with a freshly generated random token; the untrusted context calls `v8.getHeapSnapshot()` and tests UUID-shaped strings pulled from the dump [10]. Guessing is cheap because the parent answers differently: a wrong token returns an authorization error, and a correct token with invalid arguments returns a validation error [11]. The gap between those two errors is an oracle. Forged requests then go out as JSON Lines down the same standard output pipe the trusted context uses, and the parent validates the token and serves them [12].

Two things would have to be true for a CLI permission mode to be a security boundary. Write scope would have to come from the resolved real path, not the string in the patch. And no process inside the sandbox could hold a credential the unsandboxed parent honours. Neither held, and both of the modes named in the report were bypassed [1]. The two techniques otherwise share nothing but an entry condition [20]: a developer opens an untrusted repository, or instructions travel from its contents into the agent [14]. In my view that is where the isolation decision belongs, at a container or VM that mounts the repository and nothing else.

The payloads differ in timing. Heapjack fires during the question [15]. Overpatch waits for the next shell startup, with no clear warning while the patch is processed [16]. Both were patched within eight days of reporting, and public materials report no exploitation in real-world attacks [3]. The dev.to summary credits the work to Accomplish AI, published 2026-09-15 and rated high severity, and does not name the researchers [18].

What to watch

  • Whether the Codex CLI 0.149.0 release notes describe fixes for both techniques; the summary lists that release only as related material.
  • Whether node_repl stays enabled globally in ~/.codex/config.toml after the patch or moves behind an explicit opt-in.
  • Any report of the error-class oracle being reused against other MCP servers that authenticate to a privileged parent from inside a sandbox.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories