Carlos Tapia
← All notes

Three in four sandbox escapes I measured broke no configured rule

· 3 min read

the sandboxagentwork/.git/hooks/pre-commitwritesthis looks normalyou, later:git committhe hook runs outsidethat is the leak

I maintain a sandbox, tartaros (mine), so I did not write these tests. I took the 168 contracts the lab had on 15 October 2026, all from the public test suites of sandbox-runtime, nono, Codex and bubblewrap, and ran the first three against them.

Each contract has an attack, a control with legitimate work that has to keep working, and an effect checked on disk afterwards. An attack only counts if it works with no sandbox.

Resultsandbox-runtimenonoCodex
Contained993174
Escaped223324
Control broke4627
Cannot express it187818
Proves nothing878
Not on Linux / missing in the runner131313

TABLE 1 · Linux 6.8, 2026-10-15. Some results are held while a coordinated-disclosure process is open and will be published when the vendor authorizes it. «Cannot express it» is a feature the sandbox lacks.

I also sent reports to the vendors’ security programs: 4 to sandbox-runtime (one still open) and 2 to Codex (one still open). An open report stays out of the published results until it is fixed.

Most escapes are defaults

Of the 79 escapes, 61 test something no configured rule asked for, such as protecting .git/hooks inside the folder the agent can write to. That is the sandbox as it ships. 13 are confirmed failures of a configured rule.

Where the escapes come from

Escapes per sandbox, split by whether any configured rule asked for the protection.

On a default On a configured rule
0 10 20 30 sandbox-runtime — On a default 14 · On a configured rule 8 · total 22 sandbox-runtime 14 22 nono — On a default 27 · On a configured rule 6 · total 33 nono 27 33 Codex — On a default 20 · On a configured rule 4 · total 24 Codex 20 24

FIG. 1 · 61 of the 79 escapes are on the default side: the contract tests something no policy field asks for. The configured-rule segment adds escapes with a review note (5) and confirmed ones (13). One run, Linux 6.8, 2026-10-15.

Escape typesandbox-runtimenonoCodexTotal
trust-handoff7171337
isolation77519
filesystem1539
secrets2013
network5005
lifecycle0325
ipc0101
Total22332479

TABLE 2 · The 79 escapes by the lab’s category.

In a trust-handoff escape the agent writes a git hook or an editor config inside its folder, and your next git commit or your editor runs it outside the sandbox. Nine contracts escape in all three sandboxes; five of them are trust-handoff.

A «blocked» is not enough

Looking only at whether the attack failed, the three would score 111, 44 and 109 «blocked». In Codex, 27 of the 35 extra are broken controls: the attack failed and so did the legitimate work.

nono in its own model

The contracts assume everything is readable unless denied. nono works the other way: you grant the workspace and nothing else exists, so 62 of its 78 «cannot express it» say nothing about nono. In a second run I rewrote 22 of those attacks in its model without changing what they test. The rest have no equivalent.

The 22 variantssandbox-runtimenonoCodex
Contained211718
Escaped040
Control broke003
Proves nothing111

TABLE 3 · Second run, same host. nono’s 4 escapes: unix sockets the kernel does not mediate, and grants resolved through symlinks.

After this run

landrun was added the same day: 17 of its 38 escapes are trust-handoff. tartaros (mine) was measured on 22 October 2026 against 188 contracts: 150 contained, 3 escaped. Since 26 October the corpus has 196 contracts. The contracts, the runner and the current results are in the lab.

How this was measured. 168 contracts (the lab's corpus on 2026-10-15) against sandbox-runtime 0.0.79, nono 0.80.0 and Codex CLI 0.162.1 on Linux 6.8. Each attack runs first with no sandbox; every non-contained result was reviewed by hand. Results held under coordinated disclosure are not counted.

Related