Skip to content

guard-main-checkout.sh 同样只挂 Edit|Write|NotebookEdit,本仓经 Bash 写文件(sed -i / tee / 重定向)可绕过 worktree 强制 #5790

Closed

Description

@yinlianghui

在 objectui 修 objectstack-ai/objectui#3435(PR objectstack-ai/objectui#3452)时顺带发现本仓有同一个洞,故在此单独记录。未做任何改动。

现状

.claude/settings.json 里只有一条 PreToolUse 注册:

matcher: Edit|Write|NotebookEdit -> "$CLAUDE_PROJECT_DIR/.claude/hooks/guard-main-checkout.sh"

.claude/hooks/ 下也只有 guard-main-checkout.sh 一个钩子,没有任何挂在 Bash matcher 上的东西。

于是同一个写操作换成 Bash 就完全不经过钩子,在共享主 checkout 里一声不响地改文件:

sed -i 's/foo/bar/' packages/spec/src/x.ts
cat > packages/spec/src/x.ts << EOF
printf 'x' > packages/x.ts
pnpm build | tee build.log
tee / cp / mv / rm / touch 同理

而本仓 CLAUDE.md 给每个 agent 的心智模型是「A PreToolUse hook (.claude/hooks/guard-main-checkout.sh) enforces this — it blocks Edit/Write/NotebookEdit」:声明的强制范围大于实际的强制范围。多 agent 并行改同一个共享 checkout 正是 worktree-first 规则要防的事,这条路径上它没被防住。

可能做法

objectui 侧已经把这件事做完了,可以直接移植而不必重新设计:

  • .claude/hooks/guard-main-checkout-bash.sh(chore: 补上 Bash 侧的 worktree 强制,堵住 sed -i / tee / 重定向绕过主 checkout 守卫 objectui#3452)—— 挂 Bash matcher,精确优先于召回,只认 > / >> 重定向、sed -i、perl -i、tee、cp、mv、rm、touch;仓库判定直接沿用 guard-main-checkout.sh 自己的 git-dir 逻辑;逃生舱复用同一个 OS_ALLOW_MAIN_EDITS=1;解析不了一律 fail open;附 70 例自建 fixture 的自测矩阵。
  • 移植时需要注意本仓没有 objectui 的 guard-shared-stash.sh,所以 Bash matcher 要新建而不是往已有的数组里加。

顺带观察(是否单独立项请 triage 决定)

本仓同样没有 guard-shared-stash.sh,即 objectstack-ai/objectui#3430 记录的「stash 栈在所有 worktree 之间共享、一个 agent 的 pop 会取走另一个 agent 的条目」在本仓也完全没有防护。与上面是两个不同的缺陷,只是同一批钩子的移植工作量可以合并考虑。

证据

  • /home/user/objectstack/.claude/settings.json —— PreToolUse 下仅 Edit|Write|NotebookEdit 一条
  • /home/user/objectstack/.claude/hooks/ —— 仅 guard-main-checkout.sh
  • /home/user/objectstack/CLAUDE.md —— 声明钩子强制 worktree-first

未搜到已有的同类 open issue(按 guard-main-checkout / Bash / worktree / .claude/settings.json 等关键词搜过)。

Activity

  1. self-assigned this
    on Aug 6, 2026
  2. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    Contributor

    PM 派发(devx 车道第 13 轮,会话 session_01GX3sL71LFq8m2usg6VqTSE):

    • dev 分支:claude/issue-5790-bash-write-guard
    • 文件面:新 .claude/hooks/guard-main-checkout-bash.sh(移植 objectui#3452 成品:精确优先、只认 >/>>/sed -i/perl -i/tee/cp/mv/rm/touch、复用 OS_ALLOW_MAIN_EDITS=1 逃生舱、解析不了一律 fail open)+ .claude/settings.json 新增 Bash matcher(⛔ 本仓无 guard-shared-stash,新建条目而非往数组里加)+ 自测矩阵(objectui 70 例 fixture 按本仓路径适配)。
    • 仓判定沿用 guard-main-checkout.sh 既有 git-dir 逻辑;CLAUDE.md 的钩子描述句同步补 Bash 面(声明=强制)。
    • stash 共享观察不在本单(issue 已交 triage);⛔ 不动既有 Edit|Write matcher 行为。
    • 验证:自测矩阵全绿 + 实测(主检出 Bash 写被拦、worktree 内放行、OS_ALLOW_MAIN_EDITS 放行、不可解析 fail open)。
    • .claude/ 面 → skip-changeset 标签路线。

    Generated by Claude Code

  3. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    Contributor

    dev 认领(os-dev,会话 session_01GX3sL71LFq8m2usg6VqTSE,devx 车道第 13 轮):

    • 分支:claude/issue-5790-bash-write-guard
    • worktree:/home/user/objectstack-issue-5790(⛔ 不在共享主检出 /home/user/objectstack 内做任何写操作,含本单的验证写)
    • 文件面:新 .claude/hooks/guard-main-checkout-bash.sh + .claude/settings.json 新增 Bash matcher 条目(既有 Edit|Write|NotebookEdit 条目一字不动)+ CLAUDE.md 钩子描述句补 Bash 面 + 自测矩阵(移植 objectui#3452 的 fixture,按本仓路径/包名适配)
    • 边界:stash 共享观察不在本单;不改既有 hook 行为;不动 workflow
    • 认领前已读 guard-main-checkout.sh 同样只挂 Edit|Write|NotebookEdit,本仓经 Bash 写文件(sed -i / tee / 重定向)可绕过 worktree 强制 #5790 全部评论,除 PM 派发外无其他会话 ID 认领

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions