Files
xmwork/.claude/hooks/pre-commit-check.sh
T
gongzhiyong b39fbddd84 feat: add 5 more team assets (upstream sync, migration review, pre-commit hook)
Commands:
- /sync-upstream [--dry-run]   — casdoor-internal upstream sync with commit classification
- /check-migrations [repo|all] — Alembic/Prisma/Drizzle consistency checker (focuses on xiaoshou pending migrations)

Specialist agents:
- migration-reviewer — Critical/High/Low severity review for DB schema changes across
  all 6 repos (Alembic, Prisma, Drizzle, xorm Sync2, raw SQL)

Playbooks:
- playbooks/casdoor-upstream-rebase.md — quarterly upstream rebase flow
  with commit classification, batched merging, cross-repo JWT compat check, rollback criteria

Hooks (active by default via settings.json):
- .claude/hooks/pre-commit-check.sh — PreToolUse on Bash:
  * blocks inline secrets in command strings (10+ patterns: sk-ant-, ghp_, AKIA, PEM, etc.)
  * on git commit, scans staged diff for same patterns
  * blocks diffs > 5000 lines (override with [huge-diff-ok] in commit msg)
- settings.json: wire PreToolUse hook
2026-04-23 23:57:41 +08:00

77 lines
2.7 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Claude Code PreToolUse hook:
# - 扫描 Bash 命令字符串本身是否含疑似密钥
# - 对 git commit,追加扫描 staged diff
# - 拒绝超大 diff(防止 Agent 一次改太多)
# 通过方式:exit 0;阻断:exit 2(Claude 会把 stderr 作为拒绝理由展示)
set -uo pipefail
input=$(cat)
command=$(echo "$input" | jq -r '.tool_input.command // ""' 2>/dev/null || echo "")
# 空命令直接放行(其他工具触发时 command 为空)
if [[ -z "$command" ]]; then
exit 0
fi
# 疑似密钥 / 凭证 模式
patterns=(
'sk-ant-[A-Za-z0-9_-]{20,}'
'ghp_[A-Za-z0-9]{30,}'
'github_pat_[A-Za-z0-9_]{40,}'
'xox[pbar]-[A-Za-z0-9-]{20,}'
'AKIA[0-9A-Z]{16}'
'AIza[0-9A-Za-z_-]{30,}'
'-----BEGIN[[:space:]]+(RSA|OPENSSH|EC|PGP|DSA|PRIVATE)[[:space:]]+PRIVATE'
'DefaultEndpointsProtocol=https;AccountName=[^;]+;AccountKey=[A-Za-z0-9+/=]{20,}'
'SharedAccessKey=[A-Za-z0-9+/=]{20,}'
'mongodb(\+srv)?://[^:]+:[^@]+@'
'postgres(ql)?://[^:]+:[^@]+@'
)
# 1) 检查命令字符串本身(捕获内联密钥,如 git commit -m "my key sk-ant-xxx")
for p in "${patterns[@]}"; do
if echo "$command" | grep -qE -- "$p"; then
echo "[hook-block] Bash 命令字符串中检测到疑似密钥 / 连接串。已阻断。" >&2
echo "[hook-block] 匹配模式: $p" >&2
exit 2
fi
done
# 2) 如果是 git commit,追加扫描 staged diff
if [[ "$command" =~ (^|[[:space:];&|])git[[:space:]]+commit ]]; then
# 尝试提取 "cd <path> &&" 前缀,否则用 $PWD
cd_path=$(echo "$command" | grep -oE '^[[:space:]]*cd[[:space:]]+[^&;]+' | awk '{print $2}' | tr -d '\n' || true)
pushd_done=0
if [[ -n "$cd_path" && -d "$cd_path" ]]; then
pushd "$cd_path" >/dev/null 2>&1 && pushd_done=1
fi
diff_content=$(git diff --cached 2>/dev/null || true)
for p in "${patterns[@]}"; do
if echo "$diff_content" | grep -qE -- "$p"; then
echo "[hook-block] Staged diff 包含疑似密钥。请先 'git restore --staged <file>' 移除涉事文件。" >&2
echo "[hook-block] 匹配模式: $p" >&2
[[ $pushd_done -eq 1 ]] && popd >/dev/null 2>&1
exit 2
fi
done
# 超大 diff 保护
diff_lines=$(echo "$diff_content" | wc -l | tr -d ' ')
if [[ "$diff_lines" =~ ^[0-9]+$ ]] && [[ $diff_lines -gt 5000 ]]; then
echo "[hook-block] Staged diff 超过 5000 行 (实际 $diff_lines 行)。请拆分为更小粒度的提交。" >&2
echo "[hook-block] 若确实是合法的大改动,绕过:在 commit message 加 '[huge-diff-ok]'" >&2
if ! echo "$command" | grep -q '\[huge-diff-ok\]'; then
[[ $pushd_done -eq 1 ]] && popd >/dev/null 2>&1
exit 2
fi
fi
[[ $pushd_done -eq 1 ]] && popd >/dev/null 2>&1
fi
exit 0