From 390c2fe785f6d67e1279dbcb7f6b38f852bf7a87 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 27 May 2026 14:04:09 -0700 Subject: [PATCH] Convert POSIX script paths to Windows form before exec on Git Bash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #2043. On Git Bash for Windows, Claude Code hands script paths to the shim in POSIX form (`/c/Users/...`). We exec a Windows `python.exe` (the `python3` Microsoft Store stub fails the probe), and Windows Python interprets the leading `/` as the root of the current drive — `/c/...` becomes `C:\c\Users\...` or `D:\c\Users\...` depending on which drive the shell happens to be on, fails with ENOENT, and every Edit/Write/MultiEdit blocks until the session restarts. Convert absolute path args via `cygpath -w` (a Git Bash builtin) before exec. Guarded by `command -v cygpath` so macOS/Linux fall straight through unchanged; `cygpath -w` is idempotent on already-Windows paths so the rare mixed-form case is safe. Only `/*` paths are converted — Windows-form paths reaching the shim are already openable by python.exe. Verified locally: - cygpath absent on macOS → guard skips → POSIX behavior unchanged - end-to-end shim invocation with a POSIX path on macOS exits 0 - stubbed cygpath -w on /c/Users/test/hook.py produces C:\Users\test\hook.py Co-Authored-By: Claude Opus 4.7 (1M context) --- plugins/security-guidance/hooks/sg-python.sh | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/plugins/security-guidance/hooks/sg-python.sh b/plugins/security-guidance/hooks/sg-python.sh index 5a1e8032..e6ac7a80 100755 --- a/plugins/security-guidance/hooks/sg-python.sh +++ b/plugins/security-guidance/hooks/sg-python.sh @@ -22,6 +22,29 @@ # "${CLAUDE_PLUGIN_ROOT}/hooks/security_reminder_hook.py" set -e +# Git Bash / MSYS on Windows hands script paths to this shim in POSIX form +# (`/c/Users/...`). When we exec a Windows `python.exe` (which we do on +# Windows since `python3` is the Microsoft Store stub), python interprets the +# leading `/` as the root of the current drive — e.g. `/c/Users/...` becomes +# `C:\c\Users\...` or `D:\c\Users\...` (whichever drive the shell is on), +# fails with ENOENT, and every Edit/Write/MultiEdit tool use blocks until the +# session restarts. See anthropics/claude-plugins-official#2043. +# +# Fix: convert absolute path args to native Windows form via `cygpath -w` +# before exec. `cygpath` is a Git Bash builtin; it's absent on macOS/Linux, +# where the `command -v` guard makes this a no-op. `cygpath -w` is idempotent +# for already-Windows paths so the rare mixed-form case is safe. +if command -v cygpath >/dev/null 2>&1; then + converted=() + for a in "$@"; do + case "$a" in + /*) converted+=("$(cygpath -w "$a")") ;; + *) converted+=("$a") ;; + esac + done + set -- "${converted[@]}" +fi + probe() { # $1..N: the interpreter command (may be multi-word like `py -3`) # Probe writes the major version to stdout and exits 0 iff it's >=3.