57 lines
1.5 KiB
Bash
Executable File
57 lines
1.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
if ! git rev-parse --git-dir >/dev/null 2>&1; then
|
|
echo "Not inside a git repository."
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v rg >/dev/null 2>&1; then
|
|
echo "ripgrep (rg) is required for secret scanning."
|
|
exit 1
|
|
fi
|
|
|
|
staged_files=()
|
|
while IFS= read -r file; do
|
|
staged_files+=("$file")
|
|
done < <(git diff --cached --name-only --diff-filter=ACMRTUXB)
|
|
|
|
if [ "${#staged_files[@]}" -eq 0 ]; then
|
|
exit 0
|
|
fi
|
|
|
|
secret_pattern='AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{20,}|xox[baprs]-[A-Za-z0-9-]{10,}|AIza[0-9A-Za-z_-]{35}|-----BEGIN (RSA|OPENSSH|EC|DSA|PRIVATE) KEY-----|(?i)(password|passwd|pwd|secret|token|api[_-]?key|jwt_secret)\s*[:=]\s*["'"'"'][^"'"'"'\s]{8,}["'"'"']'
|
|
allow_pattern='CHANGE_ME|REDACTED|PLACEHOLDER|EXAMPLE|example|<[^>]+>'
|
|
|
|
found=0
|
|
|
|
for file in "${staged_files[@]}"; do
|
|
case "$file" in
|
|
dist/*|*.png|*.jpg|*.jpeg|*.gif|*.webp|*.pdf|*.zip|*.gz|*.exe|*.dll|*.so|*.dylib)
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
if ! content="$(git show ":$file" 2>/dev/null)"; then
|
|
continue
|
|
fi
|
|
|
|
hits="$(printf '%s' "$content" | rg -n --no-heading -e "$secret_pattern" || true)"
|
|
if [ -n "$hits" ]; then
|
|
filtered="$(printf '%s\n' "$hits" | rg -v -e "$allow_pattern" || true)"
|
|
if [ -n "$filtered" ]; then
|
|
echo "Potential secret found in staged file: $file"
|
|
printf '%s\n' "$filtered"
|
|
found=1
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if [ "$found" -ne 0 ]; then
|
|
echo
|
|
echo "Commit blocked: remove or redact secrets before committing."
|
|
exit 1
|
|
fi
|
|
|
|
exit 0
|