fix(review): pin the verified git identity across the residue probe (#9557) - #9572
Closed
wenshao wants to merge 9 commits into
Closed
fix(review): pin the verified git identity across the residue probe (#9557)#9572wenshao wants to merge 9 commits into
wenshao wants to merge 9 commits into
Conversation
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.
What this PR does
worktreeResidue— the tripwire every wave of review agents is built from — verified a tree's identity once and then ran five commands that each re-discovered the repository fromcwd, through the same.gitfile the check had read. That file is writable by anything running as this user, so the gate and the measurement were a check-then-use pair.Two halves, closing different windows:
core.worktreenames this path answers--show-toplevelwith this path — so the old gate saw itself, while every command after it measured the plant's index, which already holds the contamination as committed content. A planted standalone repo has no admin entry to round-trip.scratch-treegates its own reset on exactly this check; the reading side did not have it.--git-dir/--work-treeare pinned onto every later spawn, so a swap landing after the gate cannot redirect them either.Why it's needed
The recorded reason for not doing this (#9221, round 17) was that an explicit pin changes what
ls-filesresolves, so it needs its own round of measurement. The "own round" part was right. The rest was wrong, and this is the measurement:across all five commands the probe runs (
status --porcelain -uall -z,ls-files --others -z,ls-files -s -z,ls-files -v -z,check-ignore -z -v --stdin).And it does something. With the identity captured, then the gitfile swapped at a repository whose index already holds the mutant:
Reviewer Test Plan
How to verify
cd packages/cli && npx vitest run src/commands/review→ 3 941 passed, 1 skipped, 0 failed.New:
worktreeResiduereportsunmeasurednaming "does not point back" for a tree whose.gitwas swapped at a repo that answers for this path. The fixture asserts the genuine reading first, so it cannot pass by being unmeasurable for some other reason.Evidence (Before & After)
git init, a linked worktree, and a second repo whosecore.worktreepoints at the first.Tested on
macOS 26.6 (Darwin 25.6.0), git 2.51, Node 24,
packages/clivitest 3.2.4.Risk & Scope
Confined to
packages/cli/src/commands/review/lib/worktree.ts. One new refusal path (a gitfile whose admin entry does not round-trip isunmeasured, notclean), and an argument prefix on five commands that was measured to change nothing.The shape it refuses is one a healthy pipeline never produces:
fetch-prbuilds review worktrees withgit worktree add, which always writes the round-tripping admin entry.Linked Issues
Closes #9557. Follow-up from #9221; the class it belongs to is #9556. Stacked with #9566 in the sense that both touch
lib/worktree.ts, but the regions are disjoint and they merge cleanly in either order.中文说明
这个 PR 做了什么
worktreeResidue——每一波审查 agent 构建时都会用到的那条绊线——只校验一次树的身份,随后五条命令各自从cwd重新发现仓库,经由校验时读过的那同一个.git文件。而该文件对任何以此用户身份运行的东西都可写,因此"门"与"测量"构成了一对 check-then-use。两半,各自关掉不同的窗口:
core.worktree指向本路径的仓库,会让--show-toplevel回答本路径——于是旧的门看到的是它自己,而其后每条命令测量的是植入仓库的索引,而那个索引里早已把污染当作已提交内容。植入的独立仓库根本没有可往返的 admin 条目。scratch-tree对自己的重置正是用这道检查把关;读取侧此前没有。--git-dir/--work-tree固定到其后每一个 spawn,使门之后才落地的掉包同样无法重定向它们。为什么需要
此前"不做"的记录理由(#9221 第 17 轮)是:显式固定会改变
ls-files的解析对象,因此需要单独一轮测量。"需要单独一轮"是对的,其余是错的——这就是那次测量:覆盖探针运行的全部五条命令。
而且它确实有用。在身份已被捕获之后,把 gitfile 掉包到一个索引里已含突变体的仓库:
审查者验证方案
如何验证
cd packages/cli && npx vitest run src/commands/review→ 3 941 通过、1 跳过、0 失败。新增:对于
.git被掉包到"能为本路径作答"的仓库的树,worktreeResidue返回unmeasured并点名 "does not point back"。夹具先断言真实读数,因此它不会因为"碰巧不可测量"而通过。证据(Before & After)
测试环境
macOS 26.6(Darwin 25.6.0)、git 2.51、Node 24、
packages/clivitest 3.2.4。风险与范围
限于
packages/cli/src/commands/review/lib/worktree.ts。新增一条拒绝路径(admin 条目不能往返的 gitfile 判为unmeasured而非clean),以及五条命令上一段经测量证明零影响的参数前缀。它拒绝的形态是健康流水线永远不会产生的:
fetch-pr用git worktree add创建 review 工作树,而该命令总会写入可往返的 admin 条目。关联 Issue
Closes #9557。来自 #9221 的后续;所属类别是 #9556。与 #9566 都触及
lib/worktree.ts,但区域不相交,任意顺序都能干净合并。