## 问题 `COUNTER_DIR` 默认 `/tmp/claude-reviews`,目录名与文件名模式确定且可预测。在多用户系统上,攻击者可预先创建该目录并放入指向敏感文件的软链接;插件回写时会顺着软链接写穿目标。 由 #165 的 plan 审阅(plan-review Round 2)报为 Critical。核查后确认**归属是既存债而非该 PR 引入**,故独立成 issue。 ## 证据 目录定义与其六个派生文件(`plan-review.sh:245-266`): ```bash COUNTER_DIR="${REVIEW_COUNTER_DIR:-/tmp/claude-reviews}" mkdir -p "$COUNTER_DIR" COUNTER_FILE="$COUNTER_DIR/.review-count-${SESSION_ID}" APPROVE_MARKER="$COUNTER_DIR/.review-approved-${SESSION_ID}" DEGRADE_FILE="$COUNTER_DIR/.gemini-degraded" CONV_FILE="$COUNTER_DIR/.conversation-${SESSION_ID}" HISTORY_FILE="$COUNTER_DIR/.review-history-${SESSION_ID}" ``` 三个脚本、五处引用共用该默认值(`grep -rn '/tmp/claude-reviews' scripts/`): ``` dispatch-check.sh:10 (注释) dispatch-check.sh:29 DISPATCH_DIR= precompact-review.sh:22 COUNTER_DIR= plan-review.sh:246 COUNTER_DIR= plan-review.sh:915 DISPATCH_DIR= ``` 引入时间:`32b5191`(2026-05-18,v1.0.34)。 PR #168 之后新增第七类文件 `.so-<hash>`(second-opinion.sh 的 session key)。 ## 修复要求 **必须一次覆盖全部七类文件与三个脚本**,不能只改一处: - `.review-count-*` / `.review-approved-*` / `.gemini-degraded` / `.conversation-*` / `.review-history-*` / `.dispatch-*.json` / `.so-*` - `plan-review.sh` / `dispatch-check.sh` / `precompact-review.sh` / `second-opinion.sh` **关键约束**:`DEGRADE_FILE` 必须保持 hook 与 driver 同目录,否则降级状态共享失效(一侧探明容量耗尽、另一侧继续撞)。分批迁移会制造这个裂缝。 候选方案: 1. `${XDG_STATE_HOME:-$HOME/.local/state}/claude-reviews`(pr-review 的 session 落盘已用此惯例)或 `~/.cache/claude-reviews` —— 用户私有空间,根治可预测性 2. 保留 `/tmp` 但加权限校验:`mkdir -p` 后校验 owner 与 mode、拒绝软链接(`[ -L ]`)、`chmod 700` 倾向方案 1 —— 与仓库内既有惯例一致,且不需要每个写入点都做校验。 ## 兼容性 `REVIEW_COUNTER_DIR` 是既有的测试隔离变量,迁移须保持它仍能覆盖默认值(237+ 个 bats 用例依赖它做隔离)。 迁移会让升级后的首次调用看不到旧计数器 —— 影响可接受(计数器是 session 级短期状态,丢失只是重新计数),但要在 README 写明。 ## 验证 - [ ] 七类文件全部落新目录,`grep -rn '/tmp/claude-reviews' scripts/` 无残留 - [ ] `DEGRADE_FILE` 在 hook 与 driver 间仍共享(一侧写、另一侧读到) - [ ] `REVIEW_COUNTER_DIR` 覆盖仍生效,全量 bats 全绿 - [ ] 新目录权限 700,owner 正确
Activity