Block commits that contain secrets
Intercepts git commit commands and runs gitleaks on staged changes first.
PreToolUseBashblocking riskneeds manual checkWhat it does
Fires before Bash calls. Only commands that actually invoke git commit are intercepted; the hook runs gitleaks over staged changes and denies the commit when findings appear, so a secret never reaches history. Every other command passes through untouched.
When it runs
| Event | PreToolUse |
| Matcher | Bash |
| Scope | project |
| Platforms | macos, linux |
| Timeout | 60s |
| Requires | jq gitleaks git |
| Failure mode | block |
| Verified against | Claude Code hooks reference, event/matcher schema checked 2026-09-10 |
| Test status | needs manual check - run the test steps below before relying on it |
Config
Merge this into .claude/settings.json - or use the generator to combine hooks.
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-secret-commits.sh",
"timeout": 60
}
],
"matcher": "Bash"
}
]
}
}Script
Save as .claude/hooks/block-secret-commits.sh and chmod +x it.
#!/bin/bash
# block-secret-commits: scan staged changes before any git commit.
set -u
cmd=$(jq -r '.tool_input.command // empty')
[ -z "$cmd" ] && exit 0
case "$cmd" in
*"git commit"*) ;;
*) exit 0 ;;
esac
command -v gitleaks >/dev/null 2>&1 || exit 0
cd "${CLAUDE_PROJECT_DIR:-$PWD}" || exit 0
if ! gitleaks git --staged --no-banner . >/dev/null 2>&1; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "gitleaks found a possible secret in staged changes. Unstage or mask it, then commit again."
}
}'
exit 0
fi
exit 0
Install
- Install gitleaks and jq.
- Save the script to .claude/hooks/block-secret-commits.sh and chmod +x it.
- Add the config fragment to .claude/settings.json.
Test it
- Positive: stage a file with a fake AWS key and ask Claude to commit - the commit must be denied.
- Negative: a clean staged change commits normally.
- Negative: 'git status' and 'git diff' are not intercepted.
If it blocks something you wanted
The commit is only denied, nothing is lost. Unstage the flagged file or mask the secret, then ask Claude to commit again. If gitleaks is not installed the hook silently stands down - treat it as required, not optional.
Sources
- Claude Code hooks reference (checked 2026-09-10)
- gitleaks (checked 2026-09-10)
Related hooks
Secret scan on changed files
Runs gitleaks on every file Claude edits and warns when something looks like a secret.
PostToolUseEdit|Writereview riskneeds manual checkProtect .env and secret files
Blocks Claude from writing to .env files, keys, and credential files - unless you say otherwise.
PreToolUseEdit|Writeblocking riskneeds manual checkPro Pack (later)
Framework bundles, cross-platform scripts, tested blocking policies, and a test harness. Free recipes and the generator stay free.
Waitlist opens soon.