Repository navigation
Publish agent work from a clean repository - #2072
Merged
Merged
Conversation
ppXD
force-pushed
the
fix/keep-agent-git-hooks-out-of-capture
branch
from
October 6, 2026 11:04
8b87a80 to
f68742f
Compare
ppXD
force-pushed
the
fix/publish-agent-work-from-a-clean-repository
branch
from
October 6, 2026 11:04
ee80f5f to
81250ad
Compare
ppXD
changed the base branch from
fix/keep-agent-git-hooks-out-of-capture
to
main
October 6, 2026 16:30
After the agent's turn the branch push and its ls-remote readback still ran inside the agent-writable clone, with the network on and the clone credential re-injected into the argv. An agent that wrote its own .git during the run could then redirect or exfiltrate the token: a planted pre-push hook received the authed URL with working egress; url.insteadOf / pushInsteadOf, http.proxy and http.extraHeader rerouted or tampered the request; credential.helper and core.askPass ran code at credential resolution; and a work-tree .lfsconfig could send LFS objects elsewhere. The branch now leaves the clone as two git bundles, built by the same hardened, network-off, credential-free command the capture uses (the clone bound read-only, the bundles written outside the workspace): the cloned base, and the objects the branch adds to it. A fresh platform-owned repository imports the base as is and the added objects under transfer.fsckObjects, then runs the authenticated push, the LFS upload and the readback, so the credential and the network never meet the agent's .git. Only the added objects are checked because the remote already holds the base: a repository whose history carries an object strict fsck rejects, such as a zero-padded file mode, would otherwise lose every branch. git checks a fetched bundle from 2.46; older git imports it unchecked and leaves the remote's own receive checks, as before. A branch reset behind its base adds no object and travels in the base bundle. The clean repo checks out nothing, so a committed .lfsconfig cannot redirect LFS, whose endpoint comes from the explicit authed URL. Lock verification is off for that upload: against a remote without the locks API, git-lfs would write the authed URL, token included, into the publish repo's config. The shallow boundary and the LFS objects are copied on the host, outside any sandbox, from paths the agent controlled. The copy reads only real files inside the clone: it follows no link, opens no FIFO or other special file, and takes only paths shaped like LFS objects. A failure there surfaces as a WorkspaceException, which every caller of the push handles, rather than a raw IO exception that would fail a run that succeeded. Each attempt costs time and disk in proportion to the clone, not to the change. The agent's own commits are preserved. Revise rounds re-publish idempotently, and the publish repo is removed whether the publish succeeds or fails; a leak from a crash is reclaimed by the workspace janitor. A real agent that plants these vectors runs end to end against the publish in the sandbox lanes: Codex in the root lane, and Claude in the non-root lane, because the pinned Claude CLI refuses bypassPermissions, a Standard run's mode, to uid 0.
ppXD
force-pushed
the
fix/publish-agent-work-from-a-clean-repository
branch
from
October 6, 2026 16:30
81250ad to
0fa166e
Compare
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
ls-remotereadback ran inside the agent-writable clone, with the network on and the clone token in the argv. Vectors planted in that clone could redirect or steal the token: apre-pushhook,url.insteadOf/pushInsteadOf,http.proxy/http.extraHeader,credential.helper,core.askPass, and a work-tree.lfsconfig.git lfs pushand the readback (LocalGitWorkspaceProvider.PublishFromCleanRepoAsync). The agent's own commits are preserved.transfer.fsckObjects..git/shallowand.git/lfs/objectscopies run outside any sandbox:WorkspaceException, which every push caller handles.git lfs pushruns with-c lfs.locksverify=false, so git-lfs never writes the authed URL into the publish repo's config.pre-pushhook and aninsteadOfredirect in its.gitruns against the publish:AgentPublishIsolationE2ETests).NonRootWorkerE2ETests). The pinned Claude CLI refusesbypassPermissions, which is a Standard run's mode, to uid 0.Test plan
LocalGitWorkspaceProviderTestsrouting Theory. Three rows: platform commit, agent self-commit, multi-repo. It checks:transfer.fsckObjectsIsLfsObjectPathrows. Full UnitTests at the top of the stack: 11776 passed, 1 skipped.AgentPublishFromCleanRepoFlowTests(14 cases), on git 2.33.0, 2.50.1 and 2.56.0 with git-lfs 3.7.1:WorkspaceException[publish-fsck]and returning early.NonRootWorkerE2ETestsas uid 1654.sandbox-isolation.ymlparses, and its embedded python blocks compile.[publish-isolation-e2e] ran non-root claude-code uid=1654 confined=True