From d3025d4d193e99a97ac1068322c21fb9fd881d92 Mon Sep 17 00:00:00 2001 From: Cristian Magherusan-Stanciu Date: Tue, 6 Oct 2026 22:00:27 +0200 Subject: [PATCH] fix(scripts): make setup-git-secrets idempotent git secrets --add exits 1 for an already-registered pattern, so under set -e a second make setup-git-secrets aborted at the first custom pattern and left the GCP, Azure, database and PEM detectors unapplied. Register patterns through add_pattern, which skips ones already present and still fails on a real error. Add a second-run check to the allowlist self-test. --- .gitallowed | 6 ++--- scripts/setup-git-secrets.sh | 35 ++++++++++++++++++--------- scripts/test-git-secrets-allowlist.sh | 14 +++++++++++ 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/.gitallowed b/.gitallowed index b76481973..16f6e44f2 100644 --- a/.gitallowed +++ b/.gitallowed @@ -73,9 +73,9 @@ # suppress (confirmed empirically: without this, the .gitallowed # self-scan case below fails -- and note this comment must not spell any # of those spans out literally either, for the same reason). -^scripts/setup-git-secrets\.sh:[0-9]+:git secrets --add 'DefaultEndpointsProtoco[l]=https' # Azure Connection String$ -^scripts/setup-git-secrets\.sh:[0-9]+:git secrets --add 'postgre[s]://\[\^:\]\+:\[\^@\]\+@' # PostgreSQL$ -^scripts/setup-git-secrets\.sh:[0-9]+:git secrets --add 'mysq[l]://\[\^:\]\+:\[\^@\]\+@' # MySQL$ +^scripts/setup-git-secrets\.sh:[0-9]+:add_pattern 'DefaultEndpointsProtoco[l]=https' # Azure Connection String$ +^scripts/setup-git-secrets\.sh:[0-9]+:add_pattern 'postgre[s]://\[\^:\]\+:\[\^@\]\+@' # PostgreSQL$ +^scripts/setup-git-secrets\.sh:[0-9]+:add_pattern 'mysq[l]://\[\^:\]\+:\[\^@\]\+@' # MySQL$ # Truncated PEM placeholder used by scripts/test-git-secrets-allowlist.sh # (and by any fixture in this repo needing a non-secret PEM-shaped string): diff --git a/scripts/setup-git-secrets.sh b/scripts/setup-git-secrets.sh index f27fa86a3..e9d7bcad6 100755 --- a/scripts/setup-git-secrets.sh +++ b/scripts/setup-git-secrets.sh @@ -93,27 +93,38 @@ git secrets --register-aws echo "" echo "Adding custom secret patterns..." +# `git secrets --add` exits 1 when the pattern is already registered, which under +# `set -e` aborted a re-run at the first custom pattern and skipped the rest. +# Skip patterns already present so the script is idempotent; a real failure +# (for example an invalid regex) still stops it. +add_pattern() { + if git config --get-all secrets.patterns | grep -qxF -- "$1"; then + return 0 + fi + git secrets --add "$1" +} + # AWS patterns -git secrets --add 'AKIA[0-9A-Z]{16}' # AWS Access Key ID -git secrets --add '[^A-Za-z0-9/+=]{40}[^A-Za-z0-9/+=]' # AWS Secret Access Key -git secrets --add 'aws(.{0,20})?['\''"][0-9a-zA-Z/+]{40}['\''"]' # AWS Credentials +add_pattern 'AKIA[0-9A-Z]{16}' # AWS Access Key ID +add_pattern '[^A-Za-z0-9/+=]{40}[^A-Za-z0-9/+=]' # AWS Secret Access Key +add_pattern 'aws(.{0,20})?['\''"][0-9a-zA-Z/+]{40}['\''"]' # AWS Credentials # GCP patterns -git secrets --add 'AIza[0-9A-Za-z_-]{35}' # GCP API Key +add_pattern 'AIza[0-9A-Za-z_-]{35}' # GCP API Key # Azure patterns -git secrets --add 'DefaultEndpointsProtocol=https' # Azure Connection String +add_pattern 'DefaultEndpointsProtocol=https' # Azure Connection String # Generic secrets (require quoted values to avoid matching variable declarations) -git secrets --add 'password[[:space:]]*[=:][[:space:]]*['\''"][^'\''"]{8,}' # Password with quoted value -git secrets --add 'api[_-]?key[[:space:]]*[=:][[:space:]]*['\''"][^'\''"]{8,}' # API key with quoted value -git secrets --add 'secret[_-]?key[[:space:]]*[=:][[:space:]]*['\''"][^'\''"]{8,}' # Secret key with quoted value -git secrets --add 'BEGIN[[:space:]]((RSA|DSA|EC|OPENSSH|ENCRYPTED)[[:space:]])?PRIVATE[[:space:]]KEY-----' # PEM private keys +add_pattern 'password[[:space:]]*[=:][[:space:]]*['\''"][^'\''"]{8,}' # Password with quoted value +add_pattern 'api[_-]?key[[:space:]]*[=:][[:space:]]*['\''"][^'\''"]{8,}' # API key with quoted value +add_pattern 'secret[_-]?key[[:space:]]*[=:][[:space:]]*['\''"][^'\''"]{8,}' # Secret key with quoted value +add_pattern 'BEGIN[[:space:]]((RSA|DSA|EC|OPENSSH|ENCRYPTED)[[:space:]])?PRIVATE[[:space:]]KEY-----' # PEM private keys # Database connection strings -git secrets --add 'postgres://[^:]+:[^@]+@' # PostgreSQL -git secrets --add 'mysql://[^:]+:[^@]+@' # MySQL -git secrets --add 'mongodb(\+srv)?://[^:]+:[^@]+@' # MongoDB +add_pattern 'postgres://[^:]+:[^@]+@' # PostgreSQL +add_pattern 'mysql://[^:]+:[^@]+@' # MySQL +add_pattern 'mongodb(\+srv)?://[^:]+:[^@]+@' # MongoDB # Allowed patterns live in .gitallowed (versioned, applied by every scan, including CI). # They are matched against the whole "path:line:content" scanner output line, so an entry diff --git a/scripts/test-git-secrets-allowlist.sh b/scripts/test-git-secrets-allowlist.sh index b698c938a..735b688a3 100755 --- a/scripts/test-git-secrets-allowlist.sh +++ b/scripts/test-git-secrets-allowlist.sh @@ -40,6 +40,20 @@ if ! bash scripts/setup-git-secrets.sh > "$tmp/setup.log" 2>&1; then cat "$tmp/setup.log" >&2 exit 1 fi +# A second run must succeed and register nothing twice: `git secrets --add` +# exits 1 on an already-registered pattern, which used to abort a re-run +# half-configured. +patterns_before=$(git config --get-all secrets.patterns | wc -l) +if ! bash scripts/setup-git-secrets.sh > "$tmp/setup2.log" 2>&1; then + echo "scripts/setup-git-secrets.sh is not idempotent; second run failed:" >&2 + cat "$tmp/setup2.log" >&2 + exit 1 +fi +patterns_after=$(git config --get-all secrets.patterns | wc -l) +if [ "$patterns_before" -ne "$patterns_after" ]; then + echo "second setup run changed the pattern count: $patterns_before -> $patterns_after" >&2 + exit 1 +fi # Same HOME-isolation reason: drop the provider before any further scan. git config --unset-all secrets.providers