78 lines
2.2 KiB
Bash
Executable File
78 lines
2.2 KiB
Bash
Executable File
#!/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
|