Hook path with spaces in username executes wrong file on Windows — unquoted ~ expansion splits path at space
## Environment
- Claude Code
2.1.146 - Windows 11 Pro
10.0.26200 - Shell available to harness:
C:\WINDOWS\system32\bash.exe(WSL) - Username:
First Last(contains a space)
Hook configuration (~/.claude/settings.json)
"PreToolUse": [
{
"matcher": "Grep|Glob|Read|Search",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/cbm-code-discovery-gate"
}
]
}
]
Hook script (~/.claude/hooks/cbm-code-discovery-gate)
#!/bin/bash
GATE=/tmp/cbm-code-discovery-gate-$PPID
find /tmp -name 'cbm-code-discovery-gate-*' -mtime +1 -delete 2>/dev/null
if [ -f "$GATE" ]; then
exit 0
fi
touch "$GATE"
echo 'BLOCKED: ...' >&2
exit 2
Actual error surfaced in Claude Code
PreToolUse:Glob hook error: [~/.claude/hooks/cbm-code-discovery-gate]: /c/Users/First: line 1: syntax error near unexpected token `('
/c/Users/First: line 1: `[92A4:99D0][2024-01-03T16:14:37]i001: Burn v3.10.4.4718, Windows v10.0 (Build 19045: Service Pack 0), path: C:\Windows\Temp\{624C5BE0-18E7-442F-B3E6-37B0652242E1}\.cr\VC_redist.x64.exe'
Root cause
The harness expands ~ in the hook command field to the user's home directory but does not quote the resulting path before passing it to the shell. On Windows with a username containing a space (First Last), the expanded path is:
/c/Users/First Last/.claude/hooks/cbm-code-discovery-gate
Passed unquoted, the shell word-splits on the space and attempts to execute /c/Users/First as the script, with Last/.claude/hooks/cbm-code-discovery-gate as an argument.
In this case, C:\Users\First happens to exist on disk as a file (a stale Windows installer artifact). Bash executes its contents, producing the nonsensical error. The intended hook script is never reached.
Confirmed: Test-Path "C:\Users\First" -PathType Leaf returns True.
Security note
This is not merely a usability bug. On any Windows machine where the username contains a space, the harness will execute whatever file happens to exist at the truncated path (C:\Users\<first-word-of-username>) as a shell script, with elevated trust — in the PreToolUse hook position, that file's exit code controls whether the tool call proceeds. A malicious or corrupted file at that path could block, permit, or interfere with tool calls silently.
Expected behavior
The hook command path should be quoted or passed as an argv element, not interpolated into a shell string. Either:
- Use
["bash", "/path/to/hook"]style invocation (no shell interpolation), or - Wrap the expanded path in single quotes before handing it to the shell
Impact
Affects any Windows user whose username contains a space — a common Windows default. All PreToolUse / PostToolUse hooks silently misbehave for these users.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗