Concepts
Built-in protections
install and test scripts by design. That is arbitrary code. So the protections that matter are
the ones enforced by the sandbox boundary, not by asking the agent nicely.The sandbox is the boundary — the tool allowlist is only a courtesy
The agent is given a narrow set of tools (read, edit, search, a little git) and is
told not to reach the network or push. That keeps it on the rails, but it is not what keeps you safe: your postinstall and test scripts execute real code that no tool
allowlist governs. Safety rests entirely on the sandbox and its network policy, which are tested
directly — including against a deliberately hostile repository whose scripts try to break out.
What the sandbox guarantees
- A per-Run, throwaway VM. Every Run gets its own micro-VM (or hardened container). It never runs on the machine that hosts your data, and it is destroyed when the Run ends.
- Deny-all egress plus a derived allowlist. The only hosts the Run can reach are
the ones it needs, derived per Run: GitHub, the package registries named by your lockfile, your configured extra hosts, and the model endpoint. Everything else —
DNS included — fails at the network. Exfiltration and
git pushto anywhere else simply cannot connect. - Credentials are brokered at the edge. On an
api_keyconnection, your model key and the repository read token are injected into outbound requests outside the VM. Inside the VM they are only placeholders, so a script that dumps the environment or reads the credential files finds nothing real. - A read-only filesystem. The workspace is writable so the agent can edit your code; everything else is read-only, so a script cannot write outside the workspace.
- A pre-push gate. Nothing the VM produces reaches your repository except through a gate the worker runs — see below.
What the tool allowlist only discourages
The agent is blocked from WebFetch, WebSearch, curl, wget, git push, and shells like sudo; a hook refuses any
write to .github/, .git/, or outside the workspace. This is a
convenience — it stops the agent wandering — but a prompt-injection comment that tells the agent to do these things still changes nothing, because the same actions are denied by the
sandbox and the gate regardless.
The pre-push gate
Before a Run can open a pull request, the worker checks the exact set of file changes it produced. Any of these ends the Run with the change set kept and viewable, and nothing pushed:
- a write under
.github/(workflows, actions, CODEOWNERS) →gate_github_write; - a write to protected or secret files, or outside the workspace →
gate_protected_path; - a secret detected in the change, the summary, or the PR body →
gate_secret; - an oversized or unsupported change (too many files/lines, a submodule, an LFS pointer) → a diff/unsupported code.
The write token Fixback mints for the push is scoped to your one repository and cannot even
request the workflows or actions permission.
On an api_key connection, there is nothing to steal
This is what a hostile repository actually experiences on an api_key connection —
stated from the recorded outcome, not from intent:
On a subscription connection, your credential is readable
One connection type is different, and we say so plainly at connect time and on every Ship. A subscription credential (a Codex/ChatGPT plan) cannot be brokered the way an API
key can, so it has to live inside the sandbox — next to the code your install and test scripts run.
The warning you accept when you connect one, and again on every Ship, is exact — “Your repository's install and test scripts run next to this credential and could read it.”
For this reason, subscription connections are an advanced, opt-in mode, and a Public-tier Issue can never Ship on one.