From e7b2f839d9c4fcff24a01ff576d86f3e9113afdc Mon Sep 17 00:00:00 2001 From: Jordan Padams Date: Mon, 3 Aug 2026 09:21:08 -0700 Subject: [PATCH 1/9] Fix is_secret three-state check and use [[ ]] throughout - Add separate Check 2 for confirmed real secrets (is_secret: True), distinct from unaudited findings (is_secret absent); addresses the edge case where confirmed secrets would not cause a CI failure - Replace all [ ] conditionals with [[ ]] to satisfy SonarCloud - Renumber former Check 2 (new secrets scan) to Check 3 Co-Authored-By: Claude Sonnet 4.6 --- scripts/detect_secrets_baseline.sh | 34 +++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/scripts/detect_secrets_baseline.sh b/scripts/detect_secrets_baseline.sh index b6c3e34..d8ef7bc 100755 --- a/scripts/detect_secrets_baseline.sh +++ b/scripts/detect_secrets_baseline.sh @@ -9,9 +9,9 @@ set -e # Prefer venv's detect-secrets over system install -if [ -f "venv/bin/detect-secrets" ]; then +if [[ -f "venv/bin/detect-secrets" ]]; then DETECT_SECRETS="venv/bin/detect-secrets" -elif [ -f ".venv/bin/detect-secrets" ]; then +elif [[ -f ".venv/bin/detect-secrets" ]]; then DETECT_SECRETS=".venv/bin/detect-secrets" else DETECT_SECRETS="detect-secrets" @@ -39,8 +39,8 @@ for pat in "${GLOBAL_EXCLUDES[@]}"; do done # Per-repo excludes from .detect-secrets-ignore (one regex per line, # comments ok) -if [ -f .detect-secrets-ignore ]; then - while IFS= read -r line || [ -n "$line" ]; do +if [[ -f .detect-secrets-ignore ]]; then + while IFS= read -r line || [[ -n "$line" ]]; do [[ "$line" =~ ^[[:space:]]*# ]] && continue [[ -z "${line// }" ]] && continue EXCLUDE_ARGS+=(--exclude-files "$line") @@ -64,14 +64,14 @@ print('\n'.join(sorted(lines))) >/dev/null } -if [ "$1" = "scan" ]; then +if [[ "$1" = "scan" ]]; then $DETECT_SECRETS scan "${EXCLUDE_ARGS[@]}" > .secrets.baseline echo "Updated .secrets.baseline" echo "Next step: run 'scripts/detect_secrets_baseline.sh audit' to review and classify detected secrets." -elif [ "$1" = "audit" ]; then +elif [[ "$1" = "audit" ]]; then $DETECT_SECRETS audit .secrets.baseline else - if [ ! -f .secrets.baseline ]; then + if [[ ! -f .secrets.baseline ]]; then echo "❌ .secrets.baseline not found. Run 'scripts/detect_secrets_baseline.sh scan' to generate it." >&2 exit 1 fi @@ -83,14 +83,28 @@ with open('.secrets.baseline') as f: data = json.load(f) count = sum(1 for v in data.get('results', {}).values() for s in v if 'is_secret' not in s) print(count) ") - if [ "$unaudited" -gt 0 ]; then + if [[ "$unaudited" -gt 0 ]]; then echo "⚠️ Attention Required! ⚠️" >&2 - echo "$unaudited secret(s) in .secrets.baseline have not been audited." >&2 + echo "$unaudited finding(s) in .secrets.baseline have not been audited." >&2 echo "Run 'scripts/detect_secrets_baseline.sh audit' to review and classify each detected secret." >&2 exit 1 fi - # Check 2: Fail if any new secrets are detected that are not in the baseline + # Check 2: Fail if any audited findings are confirmed real secrets + confirmed=$(python3 -c " +import json, sys +with open('.secrets.baseline') as f: data = json.load(f) +count = sum(1 for v in data.get('results', {}).values() for s in v if s.get('is_secret') is True) +print(count) +") + if [[ "$confirmed" -gt 0 ]]; then + echo "⚠️ Attention Required! ⚠️" >&2 + echo "$confirmed real secret(s) are present in the baseline." >&2 + echo "Remove the secrets from your code and run 'scripts/detect_secrets_baseline.sh scan' to regenerate the baseline." >&2 + exit 1 + fi + + # Check 3: Fail if any new secrets are detected that are not in the baseline cp .secrets.baseline .secrets.new trap 'rm -f .secrets.new' EXIT $DETECT_SECRETS scan "${EXCLUDE_ARGS[@]}" --baseline .secrets.new From f041cc847e2d9ba94a55b6edb6e9403e49a8bf28 Mon Sep 17 00:00:00 2001 From: Jordan Padams Date: Mon, 3 Aug 2026 09:25:33 -0700 Subject: [PATCH 2/9] Refactor detect_secrets_baseline.sh for readability Restructure into named functions with clear responsibilities: - find_detect_secrets: locates the binary - build_exclude_args: assembles --exclude-files flags - baseline_fingerprints / baselines_match: clean baseline comparison using a heredoc Python block instead of inline escaped one-liners - count_findings: shared helper for unaudited/confirmed checks - check_unaudited_findings, check_confirmed_secrets, check_new_secrets: each check is its own function with a descriptive name - run_ci_checks: top-level that reads like a table of contents - case statement replaces if/elif chain for the entry point Also adds set -euo pipefail, named constants for BASELINE and BASELINE_IGNORE, inline comments on each GLOBAL_EXCLUDES entry, and a usage guard for unknown arguments. Co-Authored-By: Claude Sonnet 4.6 --- scripts/detect_secrets_baseline.sh | 305 +++++++++++++++++++---------- 1 file changed, 197 insertions(+), 108 deletions(-) diff --git a/scripts/detect_secrets_baseline.sh b/scripts/detect_secrets_baseline.sh index d8ef7bc..ad9d957 100755 --- a/scripts/detect_secrets_baseline.sh +++ b/scripts/detect_secrets_baseline.sh @@ -1,128 +1,217 @@ #!/bin/bash -# Single source of truth for detect-secrets arguments. -# Per-repo exclusions go in .detect-secrets-ignore (one regex per line, # for comments). +# +# detect_secrets_baseline.sh — manage the detect-secrets baseline for this repo. # # Usage: -# scripts/detect_secrets_baseline.sh scan # Regenerate .secrets.baseline -# scripts/detect_secrets_baseline.sh audit # Interactively audit .secrets.baseline -# scripts/detect_secrets_baseline.sh # Check for new secrets vs baseline -set -e - -# Prefer venv's detect-secrets over system install -if [[ -f "venv/bin/detect-secrets" ]]; then - DETECT_SECRETS="venv/bin/detect-secrets" -elif [[ -f ".venv/bin/detect-secrets" ]]; then - DETECT_SECRETS=".venv/bin/detect-secrets" -else - DETECT_SECRETS="detect-secrets" -fi - -# Global excludes applied in every repo +# scripts/detect_secrets_baseline.sh # CI mode: verify nothing new or unresolved +# scripts/detect_secrets_baseline.sh scan # Regenerate .secrets.baseline from scratch +# scripts/detect_secrets_baseline.sh audit # Interactively classify each finding +# +# Per-repo path exclusions go in .detect-secrets-ignore (one regex per line; # comments ok). + +set -euo pipefail + +BASELINE=".secrets.baseline" +BASELINE_IGNORE=".detect-secrets-ignore" + +# --------------------------------------------------------------------------- +# Locate detect-secrets binary (prefer local venv over system install) +# --------------------------------------------------------------------------- + +find_detect_secrets() { + if [[ -f "venv/bin/detect-secrets" ]]; then + echo "venv/bin/detect-secrets" + elif [[ -f ".venv/bin/detect-secrets" ]]; then + echo ".venv/bin/detect-secrets" + else + echo "detect-secrets" + fi +} + +DETECT_SECRETS="$(find_detect_secrets)" + +# --------------------------------------------------------------------------- +# Build --exclude-files arguments from global + per-repo patterns +# --------------------------------------------------------------------------- + +# Paths that are always excluded, regardless of repo type. GLOBAL_EXCLUDES=( - '\.secrets\..*' - '\.git.*' - '\.pre-commit-config\.yaml' - '\.mypy_cache' - '\.pytest_cache' - '\.tox' - '\.venv' + '\.secrets\..*' # the baseline files themselves + '\.git.*' # git internals + '\.pre-commit-config\.yaml' # pre-commit config (often contains hook refs) + '\.mypy_cache' # mypy type-check cache + '\.pytest_cache' # pytest cache + '\.tox' # tox environments + '\.venv' # Python virtual envs 'venv' - 'dist' - 'build' - '.*\.egg-info' - 'scripts/detect_secrets_baseline\.sh' + 'dist' # build output + 'build' # build output + '.*\.egg-info' # installed package metadata + 'scripts/detect_secrets_baseline\.sh' # this script ) -EXCLUDE_ARGS=() -for pat in "${GLOBAL_EXCLUDES[@]}"; do - EXCLUDE_ARGS+=(--exclude-files "$pat") -done - -# Per-repo excludes from .detect-secrets-ignore (one regex per line, # comments ok) -if [[ -f .detect-secrets-ignore ]]; then - while IFS= read -r line || [[ -n "$line" ]]; do - [[ "$line" =~ ^[[:space:]]*# ]] && continue - [[ -z "${line// }" ]] && continue - EXCLUDE_ARGS+=(--exclude-files "$line") - done < .detect-secrets-ignore -fi - -compare_secrets() { - diff \ - <(python3 -c " -import json, sys -with open(sys.argv[1]) as f: data = json.load(f) -lines = [f\"{k},{s['hashed_secret']}\" for k, v in data.get('results', {}).items() for s in v] -print('\n'.join(sorted(lines))) -" "$1") \ - <(python3 -c " +build_exclude_args() { + local args=() + + for pattern in "${GLOBAL_EXCLUDES[@]}"; do + args+=(--exclude-files "$pattern") + done + + # Per-repo additions from .detect-secrets-ignore + if [[ -f "$BASELINE_IGNORE" ]]; then + while IFS= read -r line || [[ -n "$line" ]]; do + [[ "$line" =~ ^[[:space:]]*# ]] && continue # skip comments + [[ -z "${line// }" ]] && continue # skip blank lines + args+=(--exclude-files "$line") + done < "$BASELINE_IGNORE" + fi + + echo "${args[@]}" +} + +# Store as an array so it expands correctly when passed to detect-secrets. +read -ra EXCLUDE_ARGS <<< "$(build_exclude_args)" + +# --------------------------------------------------------------------------- +# Helper: extract a sorted "file,hash" list from a baseline JSON file. +# Used to compare two baselines without caring about key ordering. +# --------------------------------------------------------------------------- + +baseline_fingerprints() { + local file="$1" + python3 - "$file" <<'PYTHON' import json, sys -with open(sys.argv[1]) as f: data = json.load(f) -lines = [f\"{k},{s['hashed_secret']}\" for k, v in data.get('results', {}).items() for s in v] -print('\n'.join(sorted(lines))) -" "$2") \ - >/dev/null + +with open(sys.argv[1]) as fh: + data = json.load(fh) + +fingerprints = [ + f"{filename},{secret['hashed_secret']}" + for filename, secrets in data.get("results", {}).items() + for secret in secrets +] + +print("\n".join(sorted(fingerprints))) +PYTHON } -if [[ "$1" = "scan" ]]; then - $DETECT_SECRETS scan "${EXCLUDE_ARGS[@]}" > .secrets.baseline - echo "Updated .secrets.baseline" - echo "Next step: run 'scripts/detect_secrets_baseline.sh audit' to review and classify detected secrets." -elif [[ "$1" = "audit" ]]; then - $DETECT_SECRETS audit .secrets.baseline -else - if [[ ! -f .secrets.baseline ]]; then - echo "❌ .secrets.baseline not found. Run 'scripts/detect_secrets_baseline.sh scan' to generate it." >&2 - exit 1 - fi +baselines_match() { + diff <(baseline_fingerprints "$1") <(baseline_fingerprints "$2") > /dev/null +} - # Check 1: Fail if any secrets in the baseline have not been audited - unaudited=$(python3 -c " +# --------------------------------------------------------------------------- +# Helper: count findings in a baseline that match a given Python condition. +# $1 = baseline file, $2 = Python expression that evaluates to True/False +# per secret dict (variable name: `s`) +# --------------------------------------------------------------------------- + +count_findings() { + local file="$1" + local condition="$2" + python3 - "$file" "$condition" <<'PYTHON' import json, sys -with open('.secrets.baseline') as f: data = json.load(f) -count = sum(1 for v in data.get('results', {}).values() for s in v if 'is_secret' not in s) + +with open(sys.argv[1]) as fh: + data = json.load(fh) + +condition = sys.argv[2] +count = sum( + 1 + for secrets in data.get("results", {}).values() + for s in secrets + if eval(condition) +) + print(count) -") - if [[ "$unaudited" -gt 0 ]]; then - echo "⚠️ Attention Required! ⚠️" >&2 - echo "$unaudited finding(s) in .secrets.baseline have not been audited." >&2 - echo "Run 'scripts/detect_secrets_baseline.sh audit' to review and classify each detected secret." >&2 - exit 1 +PYTHON +} + +# --------------------------------------------------------------------------- +# CI checks (default mode — no argument) +# --------------------------------------------------------------------------- + +check_unaudited_findings() { + local count + count="$(count_findings "$BASELINE" '"is_secret" not in s')" + + if [[ "$count" -gt 0 ]]; then + echo "⚠️ $count finding(s) in $BASELINE have not been audited yet." >&2 + echo " Run: scripts/detect_secrets_baseline.sh audit" >&2 + return 1 fi +} - # Check 2: Fail if any audited findings are confirmed real secrets - confirmed=$(python3 -c " -import json, sys -with open('.secrets.baseline') as f: data = json.load(f) -count = sum(1 for v in data.get('results', {}).values() for s in v if s.get('is_secret') is True) -print(count) -") - if [[ "$confirmed" -gt 0 ]]; then - echo "⚠️ Attention Required! ⚠️" >&2 - echo "$confirmed real secret(s) are present in the baseline." >&2 - echo "Remove the secrets from your code and run 'scripts/detect_secrets_baseline.sh scan' to regenerate the baseline." >&2 - exit 1 +check_confirmed_secrets() { + local count + count="$(count_findings "$BASELINE" 's.get("is_secret") is True')" + + if [[ "$count" -gt 0 ]]; then + echo "⚠️ $count confirmed secret(s) are still present in $BASELINE." >&2 + echo " Remove them from the codebase, then re-run: scripts/detect_secrets_baseline.sh scan" >&2 + return 1 fi +} + +check_new_secrets() { + local scratch="$BASELINE.new" + cp "$BASELINE" "$scratch" + trap 'rm -f "$scratch"' RETURN + + "$DETECT_SECRETS" scan "${EXCLUDE_ARGS[@]}" --baseline "$scratch" > /dev/null - # Check 3: Fail if any new secrets are detected that are not in the baseline - cp .secrets.baseline .secrets.new - trap 'rm -f .secrets.new' EXIT - $DETECT_SECRETS scan "${EXCLUDE_ARGS[@]}" --baseline .secrets.new - - if ! compare_secrets .secrets.baseline .secrets.new; then - echo "⚠️ Attention Required! ⚠️" >&2 - echo "New secrets have been detected in your recent commit. Due to security concerns, we cannot display detailed information here and we cannot proceed until this issue is resolved." >&2 - echo "" >&2 - echo "Please follow the steps below on your local machine to reveal and handle the secrets:" >&2 - echo "" >&2 - echo "1️⃣ Run the 'detect-secrets' tool on your local machine. This tool will identify and clean up the secrets. You can find detailed instructions at this link: https://nasa-ammos.github.io/slim/continuous-testing/starter-kits/#detect-secrets" >&2 - echo "" >&2 - echo "2️⃣ After cleaning up the secrets, commit your changes and re-push your update to the repository." >&2 - echo "" >&2 - echo "Your efforts to maintain the security of our codebase are greatly appreciated!" >&2 - rm -f .secrets.new + if ! baselines_match "$BASELINE" "$scratch"; then + cat >&2 <&2 exit 1 fi - rm -f .secrets.new -fi + check_unaudited_findings + check_confirmed_secrets + check_new_secrets +} + +# --------------------------------------------------------------------------- +# Entry point +# --------------------------------------------------------------------------- + +case "${1:-}" in + scan) + "$DETECT_SECRETS" scan "${EXCLUDE_ARGS[@]}" > "$BASELINE" + echo "✅ $BASELINE updated." + echo " Next: scripts/detect_secrets_baseline.sh audit" + ;; + audit) + "$DETECT_SECRETS" audit "$BASELINE" + ;; + "") + run_ci_checks + echo "✅ No new secrets detected." + ;; + *) + echo "Usage: $0 [scan|audit]" >&2 + exit 1 + ;; +esac From 69d1d55e9428486d9e68786f78d38689e159d742 Mon Sep 17 00:00:00 2001 From: Jordan Padams Date: Mon, 3 Aug 2026 09:44:41 -0700 Subject: [PATCH 3/9] Fix SonarCloud S7679: assign positional params to locals in baselines_match Co-Authored-By: Claude Sonnet 4.6 --- scripts/detect_secrets_baseline.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/detect_secrets_baseline.sh b/scripts/detect_secrets_baseline.sh index ad9d957..5148c90 100755 --- a/scripts/detect_secrets_baseline.sh +++ b/scripts/detect_secrets_baseline.sh @@ -96,7 +96,8 @@ PYTHON } baselines_match() { - diff <(baseline_fingerprints "$1") <(baseline_fingerprints "$2") > /dev/null + local a="$1" b="$2" + diff <(baseline_fingerprints "$a") <(baseline_fingerprints "$b") > /dev/null } # --------------------------------------------------------------------------- From eece7622fe266f607eceaa0bd33715af4fc48c2e Mon Sep 17 00:00:00 2001 From: Jordan Padams <33492486+jordanpadams@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:15:57 -0700 Subject: [PATCH 4/9] Fix .git exclude regex to use path-segment anchoring Avoids blocking .github/workflows/ and other .github/ paths from secrets scanning. Suggested by @nutjob4life in PR review. Co-Authored-By: Claude Sonnet 4.6 --- scripts/detect_secrets_baseline.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/detect_secrets_baseline.sh b/scripts/detect_secrets_baseline.sh index 5148c90..6ef15de 100755 --- a/scripts/detect_secrets_baseline.sh +++ b/scripts/detect_secrets_baseline.sh @@ -37,7 +37,7 @@ DETECT_SECRETS="$(find_detect_secrets)" # Paths that are always excluded, regardless of repo type. GLOBAL_EXCLUDES=( '\.secrets\..*' # the baseline files themselves - '\.git.*' # git internals + '(^|/)\.git/' # git internals (path-segment anchored to avoid blocking .github/) '\.pre-commit-config\.yaml' # pre-commit config (often contains hook refs) '\.mypy_cache' # mypy type-check cache '\.pytest_cache' # pytest cache From d3e83c9936bf43ca83c238593192ab82ff1f7e58 Mon Sep 17 00:00:00 2001 From: Jordan Padams Date: Tue, 4 Aug 2026 10:17:37 -0700 Subject: [PATCH 5/9] update secrets baseline --- .gitignore | 1 + .secrets.baseline | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c41a155..5043c91 100644 --- a/.gitignore +++ b/.gitignore @@ -140,3 +140,4 @@ override.tf.json # Ignore CLI configuration files .terraformrc terraform.rc +.envrc diff --git a/.secrets.baseline b/.secrets.baseline index 32cf433..f555a74 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -159,5 +159,5 @@ } ] }, - "generated_at": "2026-07-03T00:22:23Z" + "generated_at": "2026-08-04T17:17:22Z" } From a827c07c56a13aedb39a947eba1d8f480ef0f9b3 Mon Sep 17 00:00:00 2001 From: Jordan Padams Date: Tue, 4 Aug 2026 15:42:36 -0700 Subject: [PATCH 6/9] Fix broken detect secrets --- .detect-secrets-ignore | 8 ++++++++ scripts/detect_secrets_baseline.sh | 14 +++----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.detect-secrets-ignore b/.detect-secrets-ignore index 904a107..c638313 100644 --- a/.detect-secrets-ignore +++ b/.detect-secrets-ignore @@ -9,3 +9,11 @@ # Documentation files contain placeholder/example credentials only README\.md CHANGELOG\.md + +# Python stuff +\.mypy_cache # mypy type-check cache +\.pytest_cache # pytest cache +\.tox # tox environments +\.venv # Python virtual envs +venv +.*\.egg-info # installed package metadata \ No newline at end of file diff --git a/scripts/detect_secrets_baseline.sh b/scripts/detect_secrets_baseline.sh index 6ef15de..6327858 100755 --- a/scripts/detect_secrets_baseline.sh +++ b/scripts/detect_secrets_baseline.sh @@ -39,14 +39,11 @@ GLOBAL_EXCLUDES=( '\.secrets\..*' # the baseline files themselves '(^|/)\.git/' # git internals (path-segment anchored to avoid blocking .github/) '\.pre-commit-config\.yaml' # pre-commit config (often contains hook refs) - '\.mypy_cache' # mypy type-check cache - '\.pytest_cache' # pytest cache - '\.tox' # tox environments - '\.venv' # Python virtual envs - 'venv' + 'node_modules' # JS dependencies 'dist' # build output 'build' # build output - '.*\.egg-info' # installed package metadata + '\.venv' # Python virtual envs + 'venv' 'scripts/detect_secrets_baseline\.sh' # this script ) @@ -184,11 +181,6 @@ EOF } run_ci_checks() { - if [[ ! -f "$BASELINE" ]]; then - echo "❌ $BASELINE not found. Run: scripts/detect_secrets_baseline.sh scan" >&2 - exit 1 - fi - check_unaudited_findings check_confirmed_secrets check_new_secrets From 5f57cb04f8b77fc1effd98f5779ada38457bdf60 Mon Sep 17 00:00:00 2001 From: Jordan Padams Date: Tue, 4 Aug 2026 15:45:56 -0700 Subject: [PATCH 7/9] Update ignore --- .detect-secrets-ignore | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.detect-secrets-ignore b/.detect-secrets-ignore index c638313..8dd3929 100644 --- a/.detect-secrets-ignore +++ b/.detect-secrets-ignore @@ -11,9 +11,9 @@ README\.md CHANGELOG\.md # Python stuff -\.mypy_cache # mypy type-check cache -\.pytest_cache # pytest cache -\.tox # tox environments -\.venv # Python virtual envs +\.mypy_cache +\.pytest_cache +\.tox +\.venv venv -.*\.egg-info # installed package metadata \ No newline at end of file +.*\.egg-info \ No newline at end of file From c07a92f33d596d1339093ae8bb6009da56a99172 Mon Sep 17 00:00:00 2001 From: Jordan Padams Date: Tue, 4 Aug 2026 16:18:17 -0700 Subject: [PATCH 8/9] Fix RETURN trap referencing local var after function exit on bash 5.1 Single-quoted trap deferred expansion of scratch until after RETURN, at which point bash 5.1 (ubuntu-latest) had already unset the local, triggering set -u unbound-variable error. Double-quoting expands the path at trap-registration time while scratch is still in scope. Co-Authored-By: Claude Sonnet 4.6 --- scripts/detect_secrets_baseline.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/detect_secrets_baseline.sh b/scripts/detect_secrets_baseline.sh index 6327858..6411da0 100755 --- a/scripts/detect_secrets_baseline.sh +++ b/scripts/detect_secrets_baseline.sh @@ -153,7 +153,8 @@ check_confirmed_secrets() { check_new_secrets() { local scratch="$BASELINE.new" cp "$BASELINE" "$scratch" - trap 'rm -f "$scratch"' RETURN + # shellcheck disable=SC2064 + trap "rm -f '$scratch'" RETURN "$DETECT_SECRETS" scan "${EXCLUDE_ARGS[@]}" --baseline "$scratch" > /dev/null From ff49b255394ca610e6bb3b73ce49d6b1a9338e9f Mon Sep 17 00:00:00 2001 From: Jordan Padams Date: Wed, 5 Aug 2026 07:35:52 -0700 Subject: [PATCH 9/9] Expand .detect-secrets-ignore with Python artifacts and editor/IDE paths Add exclusions for Python build/cache artifacts (__pycache__, compiled files, packaging outputs), env template files (.env.example etc.), and editor/IDE directories (.vscode, .idea, .sublime-*) that commonly trigger false positives but never contain real secrets. Co-Authored-By: Claude Sonnet 4.6 --- .detect-secrets-ignore | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/.detect-secrets-ignore b/.detect-secrets-ignore index 8dd3929..8b5cba4 100644 --- a/.detect-secrets-ignore +++ b/.detect-secrets-ignore @@ -10,10 +10,35 @@ README\.md CHANGELOG\.md -# Python stuff +# Python artifacts and caches \.mypy_cache \.pytest_cache \.tox \.venv venv -.*\.egg-info \ No newline at end of file +.*\.egg-info +__pycache__ +.*\.pyc +.*\.pyo +.*\.pyd +.*\.so +.*\.egg +.*\.whl +.*\.pth +pip-wheel-metadata +\.Python + +# Environment / config files (may contain local paths but not real secrets) +.*\.env\.example +.*\.env\.sample +.*\.env\.template +.*\.env\.test + +# Editor and IDE artifacts +\.vscode +\.idea +.*\.sublime-workspace +.*\.sublime-project +.*\.swp +.*\.swo +.*~ \ No newline at end of file