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/...)

Offen
#94,256 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
area:hooks bug has repro platform:windows
Vorherrschende Sprache
Python
Sterne
145k
Forks
23.1k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

### 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.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.