mirror of
https://github.com/luongnv89/claude-howto.git
synced 2026-06-05 22:36:34 +02:00
fix(hooks): apply review fixes dropped by squash merge
The squash merge of PR #49 discarded two review fix commits. Re-applying: - security-scan.sh: wrap output in hookSpecificOutput (PostToolUse protocol); restore secret/token detection; fix JSON newline escaping; escape file path - validate-prompt.sh: try "user_prompt" field first, fall back to "prompt" - log-bash.sh: document sed truncation limitation for quoted commands - format-code.sh: fix misleading comment about updatedInput output
This commit is contained in:
@@ -2,8 +2,9 @@
|
|||||||
# Auto-format code before writing
|
# Auto-format code before writing
|
||||||
# Hook: PreToolUse:Write
|
# Hook: PreToolUse:Write
|
||||||
#
|
#
|
||||||
# Reads the target file path from stdin JSON and runs the appropriate formatter.
|
# Reads the target file path from stdin JSON and runs the appropriate formatter
|
||||||
# Outputs updatedInput to pass the formatted content back.
|
# 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.
|
||||||
#
|
#
|
||||||
# Compatible with: macOS, Linux, Windows (Git Bash)
|
# Compatible with: macOS, Linux, Windows (Git Bash)
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
INPUT=$(cat)
|
INPUT=$(cat)
|
||||||
|
|
||||||
# Extract the bash command from tool_input
|
# Extract the bash command from tool_input
|
||||||
|
# Note: sed [^"]* stops at escaped quotes in JSON; for commands with double-quoted
|
||||||
|
# strings, only the portion up to the first \" will be captured — this is a known
|
||||||
|
# limitation of sed-based JSON parsing and is acceptable for logging purposes.
|
||||||
COMMAND=$(echo "$INPUT" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
|
COMMAND=$(echo "$INPUT" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
|
||||||
|
|
||||||
if [ -z "$COMMAND" ]; then
|
if [ -z "$COMMAND" ]; then
|
||||||
|
|||||||
@@ -28,25 +28,31 @@ ISSUES=""
|
|||||||
|
|
||||||
# Check for hardcoded passwords
|
# Check for hardcoded passwords
|
||||||
# Handles both JSON format ("password": "value") and code format (password = 'value')
|
# Handles both JSON format ("password": "value") and code format (password = 'value')
|
||||||
|
# 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
|
if grep -qiE '"password"[[:space:]]*:[[:space:]]*"[^"]+"' "$FILE_PATH" 2>/dev/null; then
|
||||||
ISSUES="${ISSUES}- WARNING: Potential hardcoded password detected\n"
|
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)\s*=\s*'"'"'[^'"'"']+'"'"'' "$FILE_PATH" 2>/dev/null; then
|
||||||
ISSUES="${ISSUES}- WARNING: Potential hardcoded password detected\n"
|
ISSUES="${ISSUES}- WARNING: Potential hardcoded password detected\\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for hardcoded API keys
|
# Check for hardcoded API keys
|
||||||
if grep -qiE '"(api[_-]?key|apikey|access[_-]?token)"[[:space:]]*:[[:space:]]*"[^"]+"' "$FILE_PATH" 2>/dev/null; then
|
if grep -qiE '"(api[_-]?key|apikey|access[_-]?token)"[[:space:]]*:[[:space:]]*"[^"]+"' "$FILE_PATH" 2>/dev/null; then
|
||||||
ISSUES="${ISSUES}- WARNING: Potential hardcoded API key detected\n"
|
ISSUES="${ISSUES}- WARNING: Potential hardcoded API key detected\\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for hardcoded secrets and tokens
|
||||||
|
if grep -qiE '(secret|token)\s*=\s*['"'"'"][^'"'"'"]+['"'"'"]' "$FILE_PATH" 2>/dev/null; then
|
||||||
|
ISSUES="${ISSUES}- WARNING: Potential hardcoded secret or token detected\\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for private keys
|
# Check for private keys
|
||||||
if grep -q "BEGIN.*PRIVATE KEY" "$FILE_PATH" 2>/dev/null; then
|
if grep -q "BEGIN.*PRIVATE KEY" "$FILE_PATH" 2>/dev/null; then
|
||||||
ISSUES="${ISSUES}- WARNING: Private key detected\n"
|
ISSUES="${ISSUES}- WARNING: Private key detected\\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for AWS keys
|
# Check for AWS keys
|
||||||
if grep -qE "AKIA[0-9A-Z]{16}" "$FILE_PATH" 2>/dev/null; then
|
if grep -qE "AKIA[0-9A-Z]{16}" "$FILE_PATH" 2>/dev/null; then
|
||||||
ISSUES="${ISSUES}- WARNING: AWS access key detected\n"
|
ISSUES="${ISSUES}- WARNING: AWS access key detected\\n"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Scan with semgrep if available
|
# Scan with semgrep if available
|
||||||
@@ -60,8 +66,13 @@ if command -v trufflehog &> /dev/null; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# If issues found, output as additionalContext (non-blocking warning)
|
# If issues found, output as additionalContext (non-blocking warning)
|
||||||
|
# Use hookSpecificOutput format required by Claude Code PostToolUse protocol
|
||||||
if [ -n "$ISSUES" ]; then
|
if [ -n "$ISSUES" ]; then
|
||||||
printf '{"additionalContext": "Security scan found issues in %s:\n%sPlease review and use environment variables instead."}' "$FILE_PATH" "$ISSUES"
|
# Escape file path for JSON (backslash and double-quote)
|
||||||
|
# ISSUES already uses \\n as separator (valid JSON escape) — only escape double-quotes
|
||||||
|
SAFE_PATH=$(printf '%s' "$FILE_PATH" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
||||||
|
SAFE_ISSUES=$(printf '%s' "$ISSUES" | sed 's/"/\\"/g')
|
||||||
|
printf '{"hookSpecificOutput": {"hookEventName": "PostToolUse", "additionalContext": "Security scan found issues in %s:\\n%sPlease review and use environment variables instead."}}' "$SAFE_PATH" "$SAFE_ISSUES"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -10,8 +10,11 @@
|
|||||||
INPUT=$(cat)
|
INPUT=$(cat)
|
||||||
|
|
||||||
# Extract the prompt text from JSON input
|
# Extract the prompt text from JSON input
|
||||||
# Claude Code sends: {"session_id": "...", "prompt": "user's message here"}
|
# Claude Code sends UserPromptSubmit with field "user_prompt" (falls back to "prompt")
|
||||||
PROMPT=$(echo "$INPUT" | sed -n 's/.*"prompt"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
|
PROMPT=$(echo "$INPUT" | sed -n 's/.*"user_prompt"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
|
||||||
|
if [ -z "$PROMPT" ]; then
|
||||||
|
PROMPT=$(echo "$INPUT" | sed -n 's/.*"prompt"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$PROMPT" ]; then
|
if [ -z "$PROMPT" ]; then
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user