Skip to content

Sub-Agent — Secret Scanner

The single highest-value sub-agent for the Playbook’s stack. The Security Rules section covers three layers of secret protection — the .claude/settings.json denylist, CLAUDE.md rules, and Vercel’s Sensitive toggle. The Secret Scanner adds a fourth: a pre-commit pass over the staged diff to catch anything the other layers missed.

Worth installing at user scope (~/.claude/agents/) so it’s available across every project without thinking about it.

Run before every commit on any project that touches secrets. Especially valuable on the first commit after pasting real keys into .env.local (Spine step 11) — the highest-risk moment in any build.

---
name: secret-scanner
description: Use as a pre-commit guard. Scans staged changes for credentials and high-entropy strings.
tools: Read, Bash, Grep
model: haiku
---
Scan only the staged diff (`git diff --cached`), not full files. Apply three rules in order:
1. Known prefixes — match: `sk-`, `ghp_`, `AKIA`, `xoxb-`, `AIza`, `eyJ` (JWT).
2. High-entropy strings over 30 chars in suspicious keys — require BOTH a suspicious key name (`password`, `token`, `key`, `secret`, `auth`, `api_key`) AND high entropy. False positives are worse than misses on this rule.
3. Private key headers — `-----BEGIN`.
For every hit, output: file, line, masked value (first 4 + last 2 chars), and the word `BLOCK`. Never log the full secret.
If zero hits, output `PASS`.

This sub-agent does pattern matching, not reasoning. Haiku runs faster and costs less. Reserve Opus and Sonnet for the agents that need to think.

This is defence-in-depth, not a primary control. The .claude/settings.json denylist (covered in the Security Rules section) prevents Claude Code from reading .env.local in the first place; the scanner catches the case where a secret was hardcoded directly into a source file by mistake.

A pure-bash version of the same pattern, installed as .git/hooks/pre-commit (made executable with chmod +x). Runs automatically on every commit; no sub-agent invocation required. The trade-off: less context-aware (it can’t reason about whether a match is a real secret or a false positive), and it lives per-repo rather than as a user-scope agent.

#!/bin/bash
# .git/hooks/pre-commit — blocks commits containing secret patterns
PATTERNS=(
'sk-ant-' # Anthropic
'sk-live-' 'sk_live_' # Stripe
'ghp_' 'gho_' # GitHub
'AKIA' # AWS
'xox[bpors]-' # Slack
'SG\.' # SendGrid
'eyJ' # JWT
'BEGIN.*PRIVATE KEY' # Private keys
)
for pattern in "${PATTERNS[@]}"; do
if git diff --cached --diff-filter=ACM | grep -qE "$pattern"; then
echo "BLOCKED: potential secret matching '$pattern'"
exit 1
fi
done
exit 0

Use the bash hook when the project is solo and you want commit-time enforcement that can’t be skipped. Use the sub-agent when you want the same scan available across every project without per-repo setup.