feat(hooks): harden security hooks and add comprehensive test suite#48
feat(hooks): harden security hooks and add comprehensive test suite#48nwetzel22 wants to merge 1 commit into
Conversation
- dangerous-actions-blocker.sh: add credential file read blocking via grep -qP with negative lookahead to prevent false positives on template files while correctly blocking real credential files - file-guard.sh: split CRITICAL_PATTERNS into FILENAME_PATTERNS (basename glob match) and PATH_PATTERNS (substring match); add agentignore global fallback with crash-safe trap cleanup - test-hooks.sh: 94-test suite covering destructive commands, force push, credential file patterns, secret patterns, false positives, bypass detection, and agentignore integration Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FlorianBruniaux
left a comment
There was a problem hiding this comment.
Thanks for the contribution — the test suite and the FILENAME_PATTERNS/PATH_PATTERNS split are genuinely useful. Two things need to be fixed before this can merge.
Blocking
1. grep -P is not portable to macOS
dangerous-actions-blocker.sh now uses:
if echo "$COMMAND" | grep -qP "${cred_regex}(?![a-zA-Z0-9._-])"; thenBSD grep (default on macOS) does not support PCRE (-P). Since Claude Code runs heavily on macOS, this will silently break the hook for a large portion of users. Replace with a portable alternative, for example:
# Two-step: match the pattern, then confirm the next char is not alphanumeric/dot/dash
if echo "$COMMAND" | grep -q "${cred_regex}" && \
! echo "$COMMAND" | grep -q "${cred_regex}[a-zA-Z0-9._-]"; thenOr use perl which ships on both macOS and Linux:
if echo "$COMMAND" | perl -ne "exit 0 if /${cred_regex}(?![a-zA-Z0-9._-])/; exit 1"; then2. *.key, *.pem, *.p12 patterns — confirm still present
The original file-guard.sh CRITICAL_PATTERNS included *.key, *.pem, *.p12. The diff is truncated and those patterns are not visible in the new FILENAME_PATTERNS block. If they were dropped, private key files would no longer be protected — that's a regression. Please confirm they are still there (or add them back explicitly).
Minor
.pre-commit-config.yaml — anchor removal broadens the exclude scope
(?x)^(whitepapers/.*)$ was changed to (?x)(whitepapers/.*). Without ^, the pattern matches whitepapers/ anywhere in a path, not just at the root. Not a problem for this repo's current structure, but it silently changes semantics. If the goal was only to fix line length, keep the ^ anchor.
test-hooks.sh — missing jq dependency check
With set -euo pipefail active, if jq is not installed the script exits immediately with no useful message. A check at the top would help:
command -v jq >/dev/null 2>&1 || { echo "jq is required"; exit 1; }test-hooks.sh header comment — em dash
# test-hooks.sh — Tests for dangerous-actions-blocker.shThe — should be a hyphen or the sentence restructured (project style convention).
Fix the two blocking items and this is good to go.
Summary
grep -qPwith anegative lookahead (
(?![a-zA-Z0-9._-])) so real credential files are blocked but templatefiles like
dotenv.pyor env examples are correctly allowedCRITICAL_PATTERNSintoFILENAME_PATTERNS(basename glob match)and
PATH_PATTERNS(substring match); added~/.agentignoreglobal fallback with crash-safetrapcleanuppatterns, secret patterns, false positives, bypass detection, and agentignore integration
default_language_versionfrompython3.10topython3for portability; fixed
detect-aws-credentialsto useargs: [--allow-missing-credentials]instead of unsupported key; added missing
---document start; fixed line length violationTest plan
bash examples/hooks/bash/test-hooks.sh— all 94 tests should passpre-commit run --all-files— all hooks should pass🤖 Generated with Claude Code