anthropics / anthropics/claude-code

[BUG] Windows: path-guard hook shared with Linux denies every Edit/Write, even on its own settings file (tool_input.file_path is D:\... but hook shell $PWD/$HOME are POSIX /d/...)

Đang mở
#94,256 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
area:hooks bug has repro platform:windows
Ngôn ngữ chính
Python
Star
145k
Fork
23.1k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

### Environment
- Claude Code 2.1.270, native Windows 10 Pro (10.0.19045); hook commands run in Git Bash
- The same project is also used on Ubuntu. The folder is synced between the machines, so `.claude/settings.json` (permissions + hooks) is shared.

### What's wrong
The project settings contain a PreToolUse guard for `Edit|Write|NotebookEdit` that only allows files inside the project, the memory dir and the scratchpad (deny message abridged):

```json
"command": "jq -r '.tool_input.file_path // .tool_input.notebook_path // empty' | { read -r f; case \"$f\" in \"$PWD\"/*|\"$HOME\"/.claude/*|/tmp/claude-*) exit 0;; *) printf '%s' '{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"BLOCKED: file outside the project\"}}';; esac; }"
```

It works on Linux. On Windows it denies **every** Edit/Write, because the two sides of the comparison use different path formats:

| value | on Windows |
|---|---|
| `tool_input.file_path` | `D:\Dropbox\project\doc.tex` |
| `$PWD` in the hook shell (Git Bash) | `/d/Dropbox/project` |
| memory file vs `$HOME` | `C:\Users\\.claude\projects\...` vs `/c/Users/` |
| scratchpad | `C:\Users\\AppData\Local\Temp\claude\...` (Git Bash sees `/tmp/claude/...`, not `/tmp/claude-*`) |

Consequences:
1. The guard fails **closed**: every file inside the project is reported as "outside the project".
2. It also denies edits to `.claude/settings.json` itself, so the session cannot repair it. Claude is locked out, and the user has to edit the JSON by hand (or explicitly authorize a shell write that bypasses the Edit/Write diff prompt).
3. The only feedback is the hook's own deny message; nothing points to a path-format mismatch, so it looks like a permissions failure.

Because the settings are shared across machines, path rules can only be portable if they are relative to the project, and a hook is the natural place to express that. On Windows, however, the hook sees paths in a different format than its own shell.

### Related
- #83877 (closed, docs): documents that `file_path` is backslash-separated on Windows and mentions the `$PWD` trap as a fail-*open* case. The mismatch itself remains; with allow-list guards it fails closed and self-locks.
- #76490, #64432: permission rules not matching Windows paths, i.e. the same missing path normalization on Windows.

### What should happen
A settings file that works on Linux/macOS should not silently change meaning on Windows. For example:
- pass hooks paths in the format of the shell that runs them (POSIX under Git Bash), or add normalized fields next to the raw ones (e.g. `file_path_posix`, `cwd_posix`);
- expose the project and scratchpad dirs (e.g. `CLAUDE_PROJECT_DIR`) in a form directly comparable with `tool_input.file_path`;
- offer a recovery path (e.g. from `/hooks`) when a hook blocks edits to the settings file that defines it.

### Steps to reproduce
1. Native Windows, Git Bash as hook shell.
2. Put the hook above in `/.claude/settings.json`.
3. Ask Claude to edit any file in the project: denied ("outside the project").
4. Ask Claude to fix `.claude/settings.json`: denied as well.

### Workaround
Normalize both sides with `cygpath` (on Linux it does not exist and the path is used as is):

```sh
f=$(jq -r '.tool_input.file_path // .tool_input.notebook_path // empty')
u() { cygpath -u "$1" 2>/dev/null || printf '%s' "$1"; }
f=$(u "$f"); p=$(u "${CLAUDE_PROJECT_DIR:-$PWD}")
case "$f" in "$p"/*|"$HOME"/.claude/*|/tmp/claude-*|/tmp/claude/*|/c/Users/*/AppData/Local/Temp/claude/*) exit 0;; *) printf '%s' '';; esac
```

Checked on Windows: project, memory and scratchpad paths are allowed; `D:\Dropbox\other\x.tex` and `D:\Dropbox\project-other\x.tex` are denied; POSIX-style paths behave the same.

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Hướng nghiên cứu

Reproduce with the PreToolUse command in /.claude/settings.json under native Windows with Git Bash, then compare the Windows tool_input paths with the hook's $PWD/$HOME values. Check the /hooks recovery path described in the issue. Done means shared settings allow project, memory, and scratchpad edits while denying the two out-of-scope examples on Windows and Linux without locking edits to settings.json.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
bash
Lĩnh vực
cli, tooling
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
48/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.