#!/usr/bin/env bash set -euo pipefail # Lightweight staged-file secret scan for local git hygiene. # Focus: obvious high-risk mistakes, not exhaustive DLP. if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then echo "Not inside a git work tree" >&2 exit 2 fi staged_files=$(git diff --cached --name-only --diff-filter=ACMR) if [[ -z "${staged_files}" ]]; then exit 0 fi fail=0 # High-signal patterns only. Avoid noisy generic matches. patterns=( 'AKIA[0-9A-Z]{16}' 'AIza[0-9A-Za-z\-_]{35}' 'ghp_[0-9A-Za-z]{36}' 'github_pat_[0-9A-Za-z_]{20,}' 'xox[baprs]-[0-9A-Za-z-]{10,}' '-----BEGIN (RSA|DSA|EC|OPENSSH|PGP)? ?PRIVATE KEY-----' 'AIzaSy[0-9A-Za-z\-_]+' ) while IFS= read -r file; do [[ -f "$file" ]] || continue # Skip common binary assets. if file "$file" 2>/dev/null | grep -qiE 'image|font|audio|video|compressed|archive|executable'; then continue fi # Scan staged content, not working tree content. staged_content=$(git show ":$file" 2>/dev/null || true) [[ -n "$staged_content" ]] || continue for pattern in "${patterns[@]}"; do if printf '%s' "$staged_content" | grep -nE "$pattern" >/tmp/openclaw-secret-scan-match.$$ 2>/dev/null; then echo "Potential secret detected in staged file: $file" >&2 sed 's/^/ /' /tmp/openclaw-secret-scan-match.$$ >&2 || true fail=1 fi done # Heuristic: suspicious assignments for secret-ish variable names with inline values. if printf '%s' "$staged_content" | grep -nE '(^|[[:space:]])(API_KEY|TOKEN|SECRET|PASSWORD|PASSWD|PRIVATE_KEY)[[:space:]]*[:=][[:space:]]*[^[:space:]]+' >/tmp/openclaw-secret-scan-heuristic.$$ 2>/dev/null; then echo "Suspicious inline credential assignment in staged file: $file" >&2 sed 's/^/ /' /tmp/openclaw-secret-scan-heuristic.$$ >&2 || true fail=1 fi done <<< "$staged_files" rm -f /tmp/openclaw-secret-scan-match.$$ /tmp/openclaw-secret-scan-heuristic.$$ 2>/dev/null || true if [[ "$fail" -ne 0 ]]; then cat >&2 <<'EOF' Commit blocked by lightweight secret scan. If this is a false positive: - inspect the staged diff carefully - remove/redact the sensitive-looking value if needed - re-stage and commit again - or bypass once with: git commit --no-verify Use --no-verify sparingly. EOF exit 1 fi exit 0