#!/usr/bin/env bash set -euo pipefail BASE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$BASE" mode="${1:---staged}" case "$mode" in --staged) revision="--cached" ;; --worktree) revision="" ;; --history) revision="--history" ;; *) echo "Usage: $0 [--staged|--worktree|--history]" >&2; exit 2 ;; esac sensitive_names='(^|/)(\.env($|\.)|\.envrc$|\.netrc$|\.npmrc$|\.pypirc$|authorized_keys$|known_hosts$|id_(rsa|dsa|ecdsa|ed25519)(\.|$)|credentials([.-].*)?\.json$|service[-_]account.*\.json$|client[-_]secret.*\.json$|terraform\.tfstate|terraform\.tfvars)|\.(pem|key|p8|p12|pfx|jks|keystore|kdbx|age|gpg|sqlite3?|db|tfstate)(\.|$)' secret_content='AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|gh[pousr]_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|glpat-[A-Za-z0-9_-]{20,}|sk-[A-Za-z0-9_-]{20,}|AIza[0-9A-Za-z_-]{30,}|xox[baprs]-[A-Za-z0-9-]{20,}|tail[0-9a-f]{6,}\.ts\.net|-----BEGIN ([A-Z0-9 ]+ )?PRIVATE KEY-----' tracked_files() { if [[ "$mode" == "--staged" ]]; then git diff --cached --name-only --diff-filter=ACMR elif [[ "$mode" == "--worktree" ]]; then git ls-files --cached --others --exclude-standard else git log --all --pretty=format: --name-only fi } name_hits="$(tracked_files | sed '/^$/d' | sort -u | grep -E "$sensitive_names" | grep -Ev '(^|/)\.env\.example$' || true)" content_hits="" if [[ "$mode" == "--history" ]]; then while IFS= read -r commit; do hits="$(git grep -IlE -e "$secret_content" "$commit" -- . ':!tests/**' ':!scripts/check-secrets.sh' ':!frontend/package-lock.json' 2>/dev/null || true)" [[ -z "$hits" ]] || content_hits+="${hits}"$'\n' done < <(git rev-list --all) else grep_args=() if [[ "$mode" == "--worktree" ]]; then grep_args+=("--untracked" "--exclude-standard") elif [[ -n "$revision" ]]; then grep_args+=("$revision") fi content_hits="$(git grep "${grep_args[@]}" -IlE -e "$secret_content" -- . ':!tests/**' ':!scripts/check-secrets.sh' ':!frontend/package-lock.json' 2>/dev/null || true)" fi if [[ -n "$name_hits" || -n "$content_hits" ]]; then echo "ERREUR: contenu potentiellement confidentiel détecté dans Git." >&2 [[ -z "$name_hits" ]] || { echo "Fichiers au nom sensible:" >&2; printf '%s\n' "$name_hits" >&2; } [[ -z "$content_hits" ]] || { echo "Fichiers au contenu sensible:" >&2; printf '%s\n' "$content_hits" | sort -u >&2; } echo "Aucune valeur secrète n’a été affichée. Retirez le fichier de Git et révoquez toute clé réellement exposée." >&2 exit 1 fi echo "Contrôle des secrets réussi (${mode#--})."