feat(hooks): block backslashed Windows-path redirects in bash
Adds a PreToolUse(Bash) hook (block-backslash-winpath.sh) that rejects commands redirecting/writing to a backslashed Windows drive path (e.g. > D:\claudetools\ .claude\current-mode). On Git Bash those strip the backslashes and PUA-substitute ':' (U+F03A), creating garbled junk files that have repeatedly polluted the repo. The hook quote-strips the command first, so the pattern appearing inside strings or commit messages does not false-trigger; Windows-tool args (icacls, pwsh -File) and forward-slash/relative paths pass. Wired into settings.json so every machine picks it up on /sync. Pairs with the sync.sh staging guard. Also: CLAUDE.md note on the Windows mode-write path; record jq install on GURU-KALI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -67,6 +67,8 @@ echo dev > .claude/current-mode # substitute the actual mode name
|
||||
```
|
||||
This file is gitignored (machine-local). The `UserPromptSubmit` hook reads it to gate the lock check on dev mode.
|
||||
|
||||
**Windows/Git Bash:** always use the relative path above (or forward slashes — `/d/claudetools/.claude/current-mode`). NEVER a backslashed Windows path like `D:\claudetools\.claude\current-mode`: Git Bash strips the backslashes and substitutes the illegal `:` with a Unicode PUA char, creating a garbled junk file instead of writing the path. A `PreToolUse(Bash)` hook (`.claude/hooks/block-backslash-winpath.sh`) blocks such redirects; `sync.sh` also strips any that slip through before staging.
|
||||
|
||||
**Auto-initialization:** If `.claude/current-mode` is missing (e.g., fresh clone), the UserPromptSubmit hook automatically creates it with "general" as the default mode. No manual setup required.
|
||||
|
||||
---
|
||||
|
||||
37
.claude/hooks/block-backslash-winpath.sh
Executable file
37
.claude/hooks/block-backslash-winpath.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
# PreToolUse(Bash) hook: block bash commands that REDIRECT/WRITE to a backslashed
|
||||
# Windows drive path (e.g. `echo x > D:\claudetools\.claude\current-mode`).
|
||||
#
|
||||
# Why: under Git Bash / MSYS, a backslash is an escape char. `> D:\foo\bar`
|
||||
# strips the backslashes and substitutes the illegal ':' with the Unicode
|
||||
# Private-Use char U+F03A, creating a garbled junk file in the CWD instead of
|
||||
# writing the intended path. These junk files then pollute the repo. Use a
|
||||
# relative path or forward slashes (/d/claudetools/... or D:/claudetools/...).
|
||||
#
|
||||
# Only flags WRITE targets (> / >> / tee). Windows-tool arguments like
|
||||
# `icacls "D:\Homes"` or `pwsh -File C:\x.ps1` are NOT redirects, so they pass.
|
||||
|
||||
input=$(cat)
|
||||
cmd=$(echo "$input" | jq -r '.tool_input.command // ""' 2>/dev/null)
|
||||
|
||||
# Strip quoted substrings first, so the pattern appearing INSIDE a string or a
|
||||
# commit message (e.g. git commit -m "... > D:\\path ...") does not false-trigger.
|
||||
# A real bareword redirect target lives OUTSIDE quotes. (A redirect to a *quoted*
|
||||
# path like `> "D:\x"` is rarer and is still caught by sync.sh's staging guard.)
|
||||
bare=$(printf '%s' "$cmd" | sed -E "s/'[^']*'//g; s/\"[^\"]*\"//g")
|
||||
|
||||
# Block when, after quote-stripping, a redirect/tee writes to a bareword X:\ path.
|
||||
if printf '%s' "$bare" | grep -qiP '(>>?|tee)\s*[A-Za-z]:\\'; then
|
||||
echo "BLOCKED: do not redirect/write to a backslashed Windows path in bash."
|
||||
echo ""
|
||||
echo "Git Bash strips the backslashes and PUA-substitutes ':', creating a"
|
||||
echo "garbled junk file instead of writing the path you intended."
|
||||
echo ""
|
||||
echo "Use one of these instead:"
|
||||
echo " - relative path: echo dev > .claude/current-mode"
|
||||
echo " - MSYS forward-slash: echo dev > /d/claudetools/.claude/current-mode"
|
||||
echo " - drive forward-slash: echo dev > D:/claudetools/.claude/current-mode"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -33,7 +33,8 @@
|
||||
| nmap | 7.99 (Kali security tooling) |
|
||||
| GuruRMM build dev libs | libgtk-3-dev, libayatana-appindicator3-dev, libxdo-dev, libssl-dev, pkg-config (for agent + tray builds) — added 2026-05-24 |
|
||||
| NVIDIA driver | nouveau (open-source) — NO proprietary driver / CUDA |
|
||||
| jq / gh / docker / age / op / grepai / ollama | NOT installed |
|
||||
| jq | 1.8.1 (added 2026-05-24, needed by hooks) |
|
||||
| gh / docker / age / op / grepai / ollama | NOT installed |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -7,6 +7,18 @@
|
||||
"verbose": false
|
||||
},
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash -c 'h=\"${CLAUDE_PROJECT_DIR}/.claude/hooks/block-backslash-winpath.sh\"; [ -f \"$h\" ] && exec bash \"$h\" || exit 0'",
|
||||
"timeout": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"hooks": [
|
||||
|
||||
Reference in New Issue
Block a user