Conversation
Two kinds of run give Codex a cwd that is no git repository. A multi-repo run works at the workspace root, which holds each repository in a folder of its own beside a WORKSPACE.md. A repo-less run works in the scratch directory the executor makes under the temp path. Codex 0.142.2 refuses such a cwd unless it is given --skip-git-repo-check, for exec and for exec resume <id>. It exits 1 before any model request with "Not inside a trusted directory and --skip-git-repo-check was not specified", and a projects trust entry does not lift the refusal. CodeSpace never passed the flag, so every multi-repo and every repo-less Codex run failed at start. The repository-config E2E ran Codex in a single repository only, and the real-model Codex E2Es git-init a workspace of their own, so nothing caught it. Every Codex invocation now carries the flag right after --json, in both the exec seed and the exec resume seed. CodeSpace decides which directory a run works in; Codex's git heuristic should not veto it. Against the real CLI at a git cwd the flag changes nothing observable. The repository's AGENTS.md and both skill roots still load, and the untrusted marking still keeps its .codex/config.toml and hooks out. Starting at a multi-repo root exposed a gap in Codex's own workspace-write sandbox, the only boundary its commands meet where our runner does not confine. That sandbox keeps .git, .codex and .agents read-only only at the top of each writable root, so each repository's .git/hooks and .git/config were writable to the agent, and the platform's own commit and push run git there with the run's credential. Each repository below the cwd is now also named as a writable root of its own (sandbox_workspace_write.writable_roots). That adds no write access, since each is already inside the cwd. The real CLI then refuses those writes, on exec and on resume, while the agent can still change the repositories' files (observed under macOS's sandbox). A single-repo run's argv is unchanged. The real-CLI E2E now covers each change, and each new check goes red under the mutation it guards: - the multi-repo arm also plants hostile config at the workspace root, the one place Codex reads project config from in that layout, so it fails when the distrust is dropped. It is renamed to say it loads no config from that root; - a repo-less arm starts Codex in a scratch directory, and fails without the flag; - the resume stand-down arm runs at a non-git multi-repo root, so it fails without the resume seed's flag and shows the pinned CLI accepts the writable roots on resume; - a new unconfined-lane arm has the agent append to each repository's .git/hooks/pre-push, .git/config and .codex/config.toml, and fails without the writable roots. The sandbox lane's root floor moves to 92 and the unconfined lane's to 4, each requiring the new arm's marker.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
execandexec resume <id>alike, and aprojectstrust entry does not change that. Two kinds of run have such a cwd: a multi-repo run, which works at the workspace root, and a repo-less run, which works in the scratch directory fromScratchWorkspaceHandle. So every multi-repo and every repo-less Codex run failed at start.CodexHarness.BuildInvocation(backend/src/CodeSpace.Core/Services/Agents/Harnesses/Codex/CodexHarness.cs) now passes--skip-git-repo-checkon both seeds. At a git cwd the flag changes nothing the model is sent..git,.codexand.agentsread-only only at the top of each writable root. That sandbox is the only boundary where our runner does not confine. So each repository's.git/hooksand.git/configwere writable to the agent, and the platform's own commit and push run git there with the run's credential. Each repository below the cwd is now passed as-c sandbox_workspace_write.writable_roots=[...], which gives it the same carve-outs a single-repo cwd gets. No write access is added, and the single-repo argv is unchanged. Under our confinement Codex's sandbox is stood down and ignores the table.…_and_loads_no_config_from_it.UnconfinedWorkerE2ETests): the agent tries to append to each repository's.git/hooks/pre-push,.git/configand.codex/config.toml..github/workflows/sandbox-isolation.yml: root floor 92, unconfined lane 4, and the new markers are required.Not in this change: hardening the platform's own git commands against repo-local hooks and config. Under confinement that exposure already exists and is pinned by
A_standard_codex_writes_its_workspace_under_our_confinement_but_not_the_system_root. Loading sub-repository instructions at a multi-repo root is also left out.Test plan
CodexHarnessTests147/147 (argv for fresh and resumed multi-repo runs; no override for single-repo, scratch, read-only, a repository outside the cwd, or a prefix-only sibling; TOML quoting). Full unit suite: 11701 passed, 0 failedsandbox-isolation: the unconfined-lane arm is the first run of Codex's own sandbox on Linux (uid 1654); the carve-out has only been observed on macOS