| name | check-before-commit |
| description | Scan staged git changes for sensitive information before committing. Checks for API keys, credentials, infrastructure details, PII, and sensitive config files. Behavior adapts to repo visibility: blocks on public repos, warns on private repos. Supports project-level allowlist via .claude/allowlist.json. Use when: committing code, before commit, check sensitive info, pre-commit check, 扫描泄露, 检查敏感信息, commit 前检查.
|
Check Before Commit
Pre-commit sensitive information scanner. Adapts behavior based on repo visibility.
Trigger
- Automatically before
commit-commands:commit
- Manual:
/check-before-commit
Workflow
Step 1: Detect repo visibility
Run:
gh repo view --json visibility --jq .visibility 2>/dev/null
- If returns
PUBLIC → strict mode (block on findings)
- If returns
PRIVATE or INTERNAL → warn mode (report but don't block)
- If fails → ask user: "Can't detect repo visibility. Is this a public or private repo?"
Step 2: Get staged changes
Run:
git diff --cached
If no staged changes, report "No staged changes to scan" and exit.
Step 3: Load allowlist (optional)
Check for .claude/allowlist.json in project root. If exists, load the allowed array.
Items in the allowlist are skipped during scanning.
Step 4: Scan staged changes
Layer 1: Regex scan (deterministic)
Scan the diff output for these patterns:
Secrets & credentials:
sk-(live|test|proj)-[a-zA-Z0-9]{20,}
AKIA[0-9A-Z]{16}
ghp_[a-zA-Z0-9]{36}
gho_[a-zA-Z0-9]{36}
xox[bpras]-[a-zA-Z0-9-]{10,}
-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----
-----BEGIN PGP (PRIVATE KEY BLOCK|SIGNATURE)-----
Infrastructure:
# Private IPs
10\.\d{1,3}\.\d{1,3}\.\d{1,3}
172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}
192\.168\.\d{1,3}\.\d{1,3}
# Local paths (non-generic)
/Users/[^/\s]+/[^\s]*(?!\.(git|npm|cache))
/C/Users/[^/\s]+/
/home/[^/\s]+/
# Database connection strings
(postgres|mysql|mongodb|redis)://[^\s]+:[^\s]+@
Sensitive config files (check staged filenames):
.env
.env.*
*.pem
*.key
*.p12
*.pfx
.npmrc
.netrc
.ssh/
credentials
service-account*.json
For each regex match:
- Check if the matched value is in the allowlist → skip if yes
- Otherwise record as finding
Layer 2: Semantic scan (Claude judgment)
Review the diff content for PII that regex can't reliably catch:
- Phone numbers (especially Chinese mobile: 1[3-9]\d{9})
- National ID numbers (身份证号)
- Real personal names in comments or config (not variable names or git authors)
- Personal email addresses in non-git-config context
Use context to distinguish:
var userName = "test" → OK, variable value
// Contact 张三 at 13800138000 → finding, PII in comment
sk-test-1234 in test fixture → check allowlist, suggest adding if not present
Step 5: Report findings
No findings:
Output: "No sensitive information detected. Safe to commit."
→ Allow commit to proceed.
Findings + PUBLIC repo (strict mode):
Block the commit. Output each finding with:
- File and line
- Category (secret / infrastructure / PII / config file)
- The matched content (partially masked for secrets)
- Suggested action (remove / add to allowlist / use env variable)
Wait for user to fix or explicitly override.
Findings + PRIVATE repo (warn mode):
List the findings as a warning. Output same details but don't block.
User can proceed or choose to fix.
Allowlist Management
When a finding is a false positive, suggest:
"This appears to be a test/example value. Add to .claude/allowlist.json to skip in future scans?"
Format of .claude/allowlist.json:
{
"allowed": [
"sk-test-xxx",
"example@company.com",
"10.0.0.1"
]
}
If the file doesn't exist, offer to create it when the first false positive is found.
Integration with commit-commands:commit
When triggered as part of the commit workflow:
- Run this scan first
- If scan blocks (public repo + findings) → stop, don't commit
- If scan passes → proceed to normal commit flow