fix(hooks): Claude hook payload via stdin, not $CLAUDE_TOOL_USE_INPUT - #1
Closed
chenyida7-prog wants to merge 1 commit into
Closed
fix(hooks): Claude hook payload via stdin, not $CLAUDE_TOOL_USE_INPUT#1chenyida7-prog wants to merge 1 commit into
chenyida7-prog wants to merge 1 commit into
Conversation
…SE_INPUT 7ec8a2f fixed the PreToolUse matcher (Bash -> Bash|Write|Edit) so Write/Edit calls actually trigger the hook. But the hook command itself never worked: it POSTed the literal string "$CLAUDE_TOOL_USE_INPUT" as the request body (single-quoted, so the shell never expanded it — and no such env var exists anyway; Claude Code delivers the PreToolUse payload on the hook command's stdin). The backend 422'd on every single call, and curl's exit code stayed 0 on that 422, so Claude Code silently treated every operation as allowed — regardless of matcher, before or after 7ec8a2f. Fix: _hooks_command_claude() now uses `-d @-` to read the POST body from stdin, where Claude Code actually writes it. Also fixes _merge_hook_entry(): it only compared the `matcher` string when deciding whether an existing install was "already current", so once the matcher already read Bash|Write|Edit, a stale `command` (like the broken one above) would survive every future reinstall untouched. It now overwrites the whole entry whenever _matcher_is_mine() recognizes it as ours (also extended to recognize the old broken command, so an existing install upgrades in place instead of getting a duplicate matcher). Verified end-to-end in a live Claude Code session against the real KB: direct Write, Edit, and bare `rm` targeting KB files are now denied with the intended guidance message; MCP tools (write__delete_document, etc.) still pass through normally. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QqKnwdnye3njPuxqxvLSi8
Owner
|
Hook stdin 修复已收到并合入 main,非常感谢,这个修复很关键! 处理情况
WorkBuddy 验证
记录
测试
一个协作提示(非本次代码问题)
你的 fix/hook-payload-stdin 分支改动已并入 main(cherry-pick),该 PR 已过时,可以关闭。后续建议基于最新 main 开新分支协作。再次感谢! |
Owner
|
改动已通过 cherry-pick 合入 main(ee0a161),本 PR 关闭,避免与 main 上的改动重复。 |
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
7ec8a2f 修复了 PreToolUse 的 matcher(Bash → Bash|Write|Edit),让 Write/Edit
调用能真正触发 hook。但 hook 命令本身其实从没生效过:它把字面量字符串
"$CLAUDE_TOOL_USE_INPUT" POST 给后端(单引号包住导致 shell 不展开,而且这个
环境变量本身也不存在——Claude Code 是把 PreToolUse 的 payload 写到 hook 命令
的 stdin,不是环境变量)。后端每次都 422,而 curl 遇到 422 退出码仍是 0,
Claude Code 就把它当作"放行"处理——不管 matcher 覆盖了哪些工具,7ec8a2f
前后都一样,写操作从没被真正拦过。
_hooks_command_claude():改用-d @-从 stdin 读取 POST body。_merge_hook_entry():之前重装 hook 时只比较 matcher 字符串是否一致,一致就直接跳过——导致哪怕 command 是坏的,只要 matcher 已经是最新的,
重装也不会把坏 command 换掉。现在改成识别到是自己的 hook 就整体覆盖
(同时扩展识别逻辑,让装了旧版坏 command 的用户重装时能原地升级,
不会重复追加一条 matcher)。
Test plan
裸 rm 操作 KB 文件均被拦截并返回引导文案;MCP 工具(write__delete_document 等)
正常放行。
(test_upgrades_legacy_command_not_duplicated)覆盖"重装不会产生重复 matcher"。