From aa3f625c0162265144696624a2c31cb1417f5a60 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Tue, 7 Jul 2026 16:21:17 +0100 Subject: [PATCH 1/2] CCM-18514: Gitleaks Config Improvements --- .github/actions/scan-secrets/scan-secrets.sh | 110 +++++++++++++++++-- .tool-versions | 2 +- scripts/config/pre-commit.yaml | 2 +- 3 files changed, 104 insertions(+), 10 deletions(-) diff --git a/.github/actions/scan-secrets/scan-secrets.sh b/.github/actions/scan-secrets/scan-secrets.sh index 667b0eff..de08c1c6 100755 --- a/.github/actions/scan-secrets/scan-secrets.sh +++ b/.github/actions/scan-secrets/scan-secrets.sh @@ -69,8 +69,34 @@ function get-cmd-to-run() { # cmd=[command to run] function run-gitleaks-natively() { - # shellcheck disable=SC2086 - gitleaks $cmd + local output_file + output_file="$(mktemp)" + + # Prefer pseudo-terminal capture to preserve gitleaks' own colour output. + if command -v script > /dev/null 2>&1 && [ -t 1 ] && [ -z "${CI:-}" ]; then + # shellcheck disable=SC2086 + if ! script -q "$output_file" gitleaks $cmd; then + if output-has-findings "$output_file"; then + show-secret-scan-help + fi + rm -f "$output_file" + return 1 + fi + else + # shellcheck disable=SC2086 + if ! gitleaks $cmd > "$output_file" 2>&1; then + cat "$output_file" + if output-has-findings "$output_file"; then + show-secret-scan-help + fi + rm -f "$output_file" + return 1 + fi + + cat "$output_file" + fi + + rm -f "$output_file" } # Run Gitleaks in a Docker container. @@ -84,12 +110,80 @@ function run-gitleaks-in-docker() { # shellcheck disable=SC2155 local image=$(name=ghcr.io/gitleaks/gitleaks docker-get-image-version-and-pull) - # shellcheck disable=SC2086 - docker run --rm --platform linux/amd64 \ - --volume "$PWD:$dir" \ - --workdir $dir \ - "$image" \ - $cmd + local output_file + output_file="$(mktemp)" + local docker_tty_args=() + if [ -t 1 ]; then + docker_tty_args+=(--tty) + fi + + # Prefer pseudo-terminal capture to preserve gitleaks' own colour output. + if command -v script > /dev/null 2>&1 && [ -t 1 ] && [ -z "${CI:-}" ]; then + # shellcheck disable=SC2086 + if ! script -q "$output_file" docker run --rm --platform linux/amd64 \ + "${docker_tty_args[@]}" \ + --volume "$PWD:$dir" \ + --workdir $dir \ + "$image" \ + $cmd; then + if output-has-findings "$output_file"; then + show-secret-scan-help + fi + rm -f "$output_file" + return 1 + fi + else + # shellcheck disable=SC2086 + if ! docker run --rm --platform linux/amd64 \ + "${docker_tty_args[@]}" \ + --volume "$PWD:$dir" \ + --workdir $dir \ + "$image" \ + $cmd > "$output_file" 2>&1; then + cat "$output_file" + if output-has-findings "$output_file"; then + show-secret-scan-help + fi + rm -f "$output_file" + return 1 + fi + + cat "$output_file" + fi + + rm -f "$output_file" +} + +# Return success when gitleaks output appears to contain findings. +function output-has-findings() { + + [ -s "$1" ] && grep -Eq '(^|[[:space:]])(RuleID|Finding|FingerPrint):|"RuleID"' "$1" +} + +# Print clear remediation guidance when gitleaks reports findings. +function show-secret-scan-help() { + + local reset="" + local bold="" + local red="" + local yellow="" + local cyan="" + + # Use colours in interactive terminals unless explicitly disabled. + if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then + reset="\033[0m" + bold="\033[1m" + red="\033[31m" + yellow="\033[33m" + cyan="\033[36m" + fi + + printf "\n${bold}${red}[!!!] Secret scan failed.${reset}\n\n" + printf '%b\n' "${bold}${yellow}If this is a real secret:${reset}" + printf '%s\n\n' '- Remove and rotate the secret immediately.' + printf '%b\n' "${bold}${yellow}If this is a false positive:${reset}" + printf '%s\n' '- Follow PLAT-KOP-020 for handling and safely ignoring gitleaks false positives:' + printf '%b\n\n' " ${cyan}https://nhsd-confluence.digital.nhs.uk/spaces/RIS/pages/1429674058/PLAT-KOP-020+-+Handling+and+Safely+Ignoring+Gitleaks+False+Positives${reset}" } # ============================================================================== diff --git a/.tool-versions b/.tool-versions index 74dcb07e..6e647e27 100644 --- a/.tool-versions +++ b/.tool-versions @@ -8,7 +8,7 @@ terraform 1.10.1 terraform-docs 0.19.0 trivy 0.69.2 vale 3.6.0 -# python 3.13.2 +python 3.13.5 # ============================================================================== # The section below is reserved for Docker image versions. diff --git a/scripts/config/pre-commit.yaml b/scripts/config/pre-commit.yaml index 09807a1a..861a12a0 100644 --- a/scripts/config/pre-commit.yaml +++ b/scripts/config/pre-commit.yaml @@ -25,7 +25,7 @@ repos: hooks: - id: scan-secrets name: Scan secrets - entry: /usr/bin/env check=whole-history ./.github/actions/scan-secrets/scan-secrets.sh + entry: /usr/bin/env check=staged-changes ./.github/actions/scan-secrets/scan-secrets.sh language: script pass_filenames: false - repo: local From 15824fa4ad2d11531521ab3db8209624982e0ceb Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Tue, 7 Jul 2026 16:49:24 +0100 Subject: [PATCH 2/2] CCM-18514: Gitleaks Config Improvements --- .github/actions/scan-secrets/scan-secrets.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/actions/scan-secrets/scan-secrets.sh b/.github/actions/scan-secrets/scan-secrets.sh index de08c1c6..c22beaa2 100755 --- a/.github/actions/scan-secrets/scan-secrets.sh +++ b/.github/actions/scan-secrets/scan-secrets.sh @@ -182,6 +182,9 @@ function show-secret-scan-help() { printf '%b\n' "${bold}${yellow}If this is a real secret:${reset}" printf '%s\n\n' '- Remove and rotate the secret immediately.' printf '%b\n' "${bold}${yellow}If this is a false positive:${reset}" + printf '%s\n' '- For false positives introduced in your change, prefer an inline allow with a short justification.' + printf '%s\n' '- For findings that exist only in historical commits, add the fingerprint to .gitleaksignore.' + printf '%s\n' '- The gitleaks.toml allowlist is reserved for lock files and binaries; do not use it otherwise.' printf '%s\n' '- Follow PLAT-KOP-020 for handling and safely ignoring gitleaks false positives:' printf '%b\n\n' " ${cyan}https://nhsd-confluence.digital.nhs.uk/spaces/RIS/pages/1429674058/PLAT-KOP-020+-+Handling+and+Safely+Ignoring+Gitleaks+False+Positives${reset}" }