Skip to content

fix(safety): O127 L3 follows linked-worktree .git file (exec keys no longer missed) [depends #117 #122] - #124

Merged
QiaolongLi1201 merged 8 commits into
mainfrom
fix/o127-linked-worktree-exec-keys
Oct 12, 2026
Merged

QiaolongLi1201 merged 8 commits into
mainfrom
fix/o127-linked-worktree-exec-keys

Conversation

@QiaolongLi1201

@QiaolongLi1201 QiaolongLi1201 commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

人工实现(不走自举)。O127,P1 safety。

⚠️ 依赖 #117、#122:本分支叠在 #122 head 05d9c023(其下是 #117 6f419e2b)上,diff 会含两者改动;#117/#122 合入后 rebase 到 main。

根因

L3 快照 listWatchedProtectedPaths 固定监视 <cwd>/.git/...。在 linked worktree 里 .git 是文件(gitdir: <main>/.git/worktrees/<name>),这些路径都不存在,真正的共享 config(commondir)和本 worktree 的 config.worktree/HEAD 完全没进快照 → git config core.sshCommand / core.fsmonitor、config --worktree core.hooksPath 改了都不报(实测 [])。base 就有,QA 在 #117 复审 N1 发现。

改法(src/safety/protected-path-snapshot.ts)

  • 新增 resolveGitDirs(ws):纯 fs 读 .git 文件 → gitdir → commondir,不在被测仓库跑 git。
  • 原 .git 监视逻辑抽成 watchGitDir(commonDir);linked 时额外监视 .git 文件本身、<gitdir>/config.worktree、<gitdir>/HEAD。
  • .git 文件 fail-closed:内容改写 → gitlink-rewritten「.git 被改写(worktree 的 gitdir 指向变了)」;gitdir/commondir 不存在或读不了 → gitlink-missing「.git 指向的 gitdir 不存在或读不了」;软链/目录/删除照旧报。
  • .git/worktrees/<n>/HEAD 归入 O123 HEAD 规则(内容合法的 commit/checkout 不报)。
  • 键判定、放行名单、git config --file --no-includes 临时目录解析、解析失败 fail-closed 全部沿用 O117,未放松;事前拦截(fix(safety): O103 pre-block dangling symlinks, curl/wget output, git core.hooksPath #115/O103,protected-paths.ts)未改。

测试 test/o127-linked-worktree-exec-keys.spec.mjs

  • A:worktree 内 core.sshCommand、core.fsmonitor、大小写变体 CORE.FsMonitor、remote.origin.uploadpack → 点名键;config --worktree core.hooksPath → 报 .git/worktrees/<n>/config.worktree;事前:hooksPath、直写 gitdir config.worktree、写 .git 文件都被 findShellProtectedWrites 拦。
  • B:worktree 内 user.name/color.ui、git commit、checkout -b → 静默。
  • C:.git 改写、gitdir 删除、共享 config 解析失败、.git 换软链 → 报并写原因。
  • D:主仓启动行为不变。
  • G:进程级 moss -p(zh/en)在 worktree 里跑 git config core.sshCommand … → exit 9 点名键;git config user.name x → exit 0。
  • 撤修复(src 还原到 05d9c023)→ 15 failure(s)(共 27 项)。
  • 回归(Node 22.16):o117 / o123 / o101 / o103-blocked-outcome / o103-protected-path-gaps / o108 / o94 / git-spawn 全绿;npm run check 绿;npm test 374 个文件全过。

追加:自举 S2 误报(worktree 根目录「受保护路径被拦」)

  • 复现:S2 日志 Blocked: shell /workspace/selfhost-b1/s2-o74-deepseek-flash … (git repository internals),命令 cd <worktree 根> && node --test … 2>&1 | tail -25。直调 findShellProtectedWrites 复现;主仓根目录同样复现,不是 linked worktree 特有,也不是事后快照。单纯 git status / ls / cat .git / git log 在 worktree 根跑(含 -p)本来就不报。
  • 根因(事前层):node <script> 属于「拿不准」(脚本能写任何东西),于是逐个检查命令里提到的路径;cd 的目标就是工作区根,被 deletesProtectedAncestor(「删掉它就删掉 .git」)判成 git 内部 → -p 直接拒。cd 的目标从来不是写入对象。
  • 改法(protected-paths.ts,最小改动):新增 cdOnlyOperands:只出现在纯 cd/pushd <dir> 位置(无 $/反引号/~)、命令其它地方没再出现的路径,在「拿不准」分支里跳过祖先删除规则;正常受保护分类(.git、.ssh、.env…)照旧。确定的写目标、O101 内联代码/脚本扫描、O103 hooksPath 都不变。
  • 仍会拦(P2):cd <root> && node x.mjs <root>(含尾斜杠)、node x.mjs <root>、cd <root> && rm -rf <root>、> .git、cd <main>/.git && node x、node -e "rmSync('.git')"。
  • 测试:P1(worktree/主仓根 cd && node … 无命中)、P2、G3(-p 在 worktree 根:git status、ls -la、cat .git、git log、cd <root> && git status、cd <root> && node ro.mjs、cd <root> && node --test … | tail → exit 0,工具结果与输出无「被拦/已被修改」)。只撤 protected-paths.ts → 3 failure(s)(P1、G3 两条 cd && node)。

风险

  • 非标准布局(--separate-git-dir、gitdir 不叫 .git/...)下 config 路径不匹配 isGitConfigPath,会退化成整文件报(更严,可能误报良性键),不会漏报。
  • 事前层对 git config core.sshCommand 等非 hooksPath 键本来就不拦(主仓也一样,O103 范围外),本单靠事后 exit 9 覆盖。
  • 展示路径在 worktree 外时是绝对路径(如 /…/main/.git/config)。
  • 事前层:cd / && node x.mjs、cd ~/.. && node x 这类 cd 到 home/工作区祖先再跑脚本,以前因「祖先删除」被拦,现在不拦(cd 本身不写;若路径在命令别处出现仍拦)。脚本内容仍由 O101 扫描层检查。
  • 需要 QA 安全复审。

10-12 PM 裁定补丁(82eb0b43)

cd/pushd 豁免只在目标 realpath == 工作区根时生效。新增 P3:cd <工作区根> && node x 不拦;cd / && node x、cd ~ && node x 仍提示。撤此修复 → P3 红(cd / 被放过)。

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@QiaolongLi1201
QiaolongLi1201 force-pushed the fix/o127-linked-worktree-exec-keys branch from acb8408 to 82eb0b4 Compare October 12, 2026 05:52
…ir change

QA B1: exemption checked only that the first cd operand was the workspace
root, so `cd <ws> && cd && node x`, `cd <ws> && cd $HOME && node x`, and
similar follow-up cd/pushd/popd/chdir (any operand) stayed silent. Count
directory-changing builtins; allow the exemption only when there is at most
one. Add P4 regression tests that go red when this guard is reverted.
@QiaolongLi1201
QiaolongLi1201 force-pushed the fix/o127-linked-worktree-exec-keys branch from 82eb0b4 to 3ec69ed Compare October 12, 2026 06:18
@QiaolongLi1201
QiaolongLi1201 merged commit 4407b4d into main Oct 12, 2026
10 of 12 checks passed
QiaolongLi1201 added a commit that referenced this pull request Oct 12, 2026
@QiaolongLi1201
QiaolongLi1201 deleted the fix/o127-linked-worktree-exec-keys branch October 12, 2026 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant