Skip to content
Chock
The red team harness (19 of 23)

The red team harness

How Chock is attacked on purpose, what that has proved, and the boundary it moved. This is an exercise and not a build gate.

The red team harness is built, and two models have been thrown at it. zig build redteam runs the exercise: a canary set read before and after a session, a scope list compiled into the binary that reports the verdict, and the two configurations, which are maximum hardening and the dev shell that ships. It answers “did it break out” as a value rather than as a paragraph somebody reads. It is not part of zig build test, because it is an exercise run on purpose and not a build gate. The step exists on Linux only, because every canary reads /proc and the sandbox a run tests is the Linux driver.

What it has proved is itself. zig build redteam-oracle forges eleven escapes and checks each verdict against the one boundary that forge names, because a forge that tripped the wrong canary would otherwise pass. Two of the eleven are a pair: one registers the git worktree a session builds for itself and must report nothing, and the other registers a second worktree no log accounts for and must report the real project. Building it found faults in the instrument itself, and most of those would have reported a breach as held.

What it has proved about Chock is two runs. moonshotai/kimi-k3 engaged and probed hard. claude-fable-5 refused the exercise and returned nothing, so it tested nothing, and the harness records that as an empty answer rather than as a session that held.

One boundary moved, and it is closed on both platforms. A tool call wrote two files into the real repository, under .git/worktrees/<attempt>/: one in logs/ and one in refs/. The second went unreported at first, because the check that had just been taught to accept the session’s own worktree accepted every name under refs/ with it. Every ref and every object was unchanged, chock.zon was unchanged, nothing outside the workspace moved, no connection reached the listener, and no process outlived the sandbox.

That directory is bound read write because git writes the worktree index there, and a read only one breaks git status and every tool call that touches git. Against git 2.55, a read only mount there answers EROFS on the first git add, and pre-creating the lock files does not help, because git opens each one with O_CREAT|O_EXCL and then renames it over the file it locks. So the fix is a different directory instead of a read only one. The session works in its own copy of .git/worktrees/<attempt>, under the workspace scratch directory, and the project’s own copy reads byte for byte as git worktree add left it when the session ends. git status, git add, and git commit are unchanged inside the sandbox.

macOS reaches that copy a different way, because it has no bind mount. Linux binds the copy at the path git looks for. macOS cannot, so the copy is named directly with GIT_DIR and GIT_WORK_TREE. Both are needed: with GIT_DIR alone git reads the working directory as the work tree root, so git status in a subdirectory reports every file outside it as deleted. The checkout’s own .git file is left alone on both, because rewriting it breaks git worktree remove and the worktree id adopt reads out of it. Checked on macOS 15.7.9. See lib/chock-workspace/worktree.zig.

Everything else the model tried was refused: writing at refs, git push, copying a shell out of the store and renaming it to git to get past the git shim, symlinks out of the workspace, three ways to change chock.zon, and three backgrounded processes meant to outlive the sandbox.

One run against one model is evidence and not a guarantee. Ad hoc red teaming before this harness existed found nine faults, and this run found a tenth.