fix(hooks): Windows Git Bash compatibility + stdin JSON protocol (#55)

* fix(hooks): make hook scripts compatible with Windows Git Bash and use stdin JSON protocol

- Replace `grep -P` (Perl regex) with `sed` for JSON field extraction,
  as Windows Git Bash does not support `grep -P`
- Replace positional arg (`$1`) with stdin JSON parsing to match the
  actual Claude Code hook protocol (hooks receive data via stdin, not args)
- Fix JSON double-quote escaping in grep patterns that silently fails
  on Windows Git Bash
- Remove python3 dependency for JSON parsing, making scripts portable
- Add Windows Git Bash to compatibility notes in script headers

Affected scripts: security-scan.sh, validate-prompt.sh, log-bash.sh, format-code.sh

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(hooks): address review issues in Windows Git Bash compatibility scripts

- security-scan.sh: wrap output in hookSpecificOutput format required by
  PostToolUse protocol; restore secret/token detection pattern that was
  dropped; escape file path and issues for safe JSON construction
- validate-prompt.sh: extract "user_prompt" field first (Claude Code
  UserPromptSubmit protocol), falling back to "prompt"
- log-bash.sh: document sed truncation limitation for commands with
  double-quoted strings
- format-code.sh: fix misleading comment about updatedInput output

* fix(hooks): produce valid JSON from security-scan.sh

- Use \\n (JSON newline escape) when building ISSUES, not real newlines,
  so the value passes safely through printf into the JSON string
- Remove the real-newline-to-\\n sed pass (no longer needed)
- Output is now verifiably valid JSON per python3 json.loads

* fix(hooks): fix grep -E POSIX compat and semgrep/trufflehog stdout mixing

- Replace \s with [[:space:]] in grep -E patterns (security-scan.sh lines
  34,44): \s is a Perl extension, silently fails on macOS BSD grep and
  BusyBox — password/secret detection was a no-op on macOS
- Suppress stdout of semgrep/trufflehog (>/dev/null) to prevent their
  output mixing with hookSpecificOutput JSON, which would produce invalid
  JSON and cause the additionalContext to fail parsing
- Fix format-code.sh hook comment: PreToolUse → PostToolUse (matches
  README example and actual hook behavior)

---------

Co-authored-by: Bruce <binyuli1993@foxmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Luong NGUYEN
2026-04-07 08:53:32 +02:00
committed by GitHub
parent f53d08098e
commit 2cbb10c959
2 changed files with 9 additions and 10 deletions
+3 -4
View File
@@ -1,10 +1,9 @@
#!/bin/bash
# Auto-format code before writing
# Hook: PreToolUse:Write
# Auto-format code after writing
# Hook: PostToolUse:Write
#
# Reads the target file path from stdin JSON and runs the appropriate formatter
# in-place on the existing file (if it already exists on disk). For new files,
# formatting runs after Claude writes the file via a subsequent PostToolUse hook.
# in-place on the file after Claude writes it.
#
# Compatible with: macOS, Linux, Windows (Git Bash)
+6 -6
View File
@@ -31,7 +31,7 @@ ISSUES=""
# Use \\n as separator — it is a valid JSON newline escape and passes through printf safely
if grep -qiE '"password"[[:space:]]*:[[:space:]]*"[^"]+"' "$FILE_PATH" 2>/dev/null; then
ISSUES="${ISSUES}- WARNING: Potential hardcoded password detected\\n"
elif grep -qiE '(password|passwd|pwd)\s*=\s*'"'"'[^'"'"']+'"'"'' "$FILE_PATH" 2>/dev/null; then
elif grep -qiE '(password|passwd|pwd)[[:space:]]*=[[:space:]]*'"'"'[^'"'"']+'"'"'' "$FILE_PATH" 2>/dev/null; then
ISSUES="${ISSUES}- WARNING: Potential hardcoded password detected\\n"
fi
@@ -41,7 +41,7 @@ if grep -qiE '"(api[_-]?key|apikey|access[_-]?token)"[[:space:]]*:[[:space:]]*"[
fi
# Check for hardcoded secrets and tokens
if grep -qiE '(secret|token)\s*=\s*['"'"'"][^'"'"'"]+['"'"'"]' "$FILE_PATH" 2>/dev/null; then
if grep -qiE '(secret|token)[[:space:]]*=[[:space:]]*['"'"'"][^'"'"'"]+['"'"'"]' "$FILE_PATH" 2>/dev/null; then
ISSUES="${ISSUES}- WARNING: Potential hardcoded secret or token detected\\n"
fi
@@ -55,14 +55,14 @@ if grep -qE "AKIA[0-9A-Z]{16}" "$FILE_PATH" 2>/dev/null; then
ISSUES="${ISSUES}- WARNING: AWS access key detected\\n"
fi
# Scan with semgrep if available
# Scan with semgrep if available (stdout suppressed to avoid mixing with JSON output)
if command -v semgrep &> /dev/null; then
semgrep --config=auto "$FILE_PATH" --quiet 2>/dev/null
semgrep --config=auto "$FILE_PATH" --quiet >/dev/null 2>/dev/null
fi
# Scan with trufflehog if available
# Scan with trufflehog if available (stdout suppressed to avoid mixing with JSON output)
if command -v trufflehog &> /dev/null; then
trufflehog filesystem "$FILE_PATH" --only-verified --quiet 2>/dev/null
trufflehog filesystem "$FILE_PATH" --only-verified --quiet >/dev/null 2>/dev/null
fi
# If issues found, output as additionalContext (non-blocking warning)