From 07822af6a36052374bbc5e45fac93c36f58f43b0 Mon Sep 17 00:00:00 2001 From: linhchi Date: Mon, 24 Aug 2026 10:51:01 +0700 Subject: [PATCH 1/3] fix: remove fail if missing trailer and add more in4 when fail betterleaks-Scan: passed --- .github/workflows/scan-secret.yml | 95 ++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 8 deletions(-) diff --git a/.github/workflows/scan-secret.yml b/.github/workflows/scan-secret.yml index c1a4e55..f467dda 100644 --- a/.github/workflows/scan-secret.yml +++ b/.github/workflows/scan-secret.yml @@ -10,6 +10,7 @@ permissions: actions: read jobs: check-trailer: + name: Betterleaks Trailer Report if: github.event.pull_request.user.login != 'dependabot[bot]' runs-on: trivy-dind steps: @@ -19,12 +20,14 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - - name: Validate betterleaks trailer + - name: Report commits missing betterleaks trailer run: | set -euo pipefail base_sha="${{ github.event.pull_request.base.sha }}" head_sha="${{ github.event.pull_request.head.sha }}" + base_ref="${{ github.event.pull_request.base.ref }}" + repository_url="${{ github.server_url }}/${{ github.repository }}" echo "Checking PR commit range: ${base_sha}..${head_sha}" mapfile -t commits < <(git rev-list --reverse "${base_sha}..${head_sha}") @@ -32,26 +35,102 @@ jobs: commits=("${head_sha}") fi - failed=0 + missing_shas=() + missing_types=() + missing_subjects=() + for sha in "${commits[@]}"; do - echo "=== Commit ${sha} ===" + echo "========== Commit ${sha} ==========" msg="$(git log -1 --pretty=%B "${sha}")" echo "${msg}" trailers="$(printf "%s" "${msg}" | git interpret-trailers --parse)" - echo "=== Parsed trailers for ${sha} ===" + echo "Parsed trailers for ${sha}" echo "${trailers}" if printf "%s\n" "${trailers}" | grep -q "^betterleaks-Scan: passed$"; then echo "Trailer OK for ${sha}" else - echo "Missing or invalid betterleaks-Scan trailer in ${sha}" - failed=1 + echo "MISSING or INVALID betterleaks-Scan trailer in ${sha}" + missing_shas+=("${sha}") + + parent_count="$(git rev-list --parents -n 1 "${sha}" | awk '{print NF - 1}')" + if [ "${parent_count}" -gt 1 ]; then + missing_types+=("merge") + else + missing_types+=("regular") + fi + + subject="$(git log -1 --format=%s "${sha}")" + missing_subjects+=("${subject//$'\r'/ }") fi done - if [ "${failed}" -ne 0 ]; then - exit 1 + missing_count="${#missing_shas[@]}" + + { + echo "# Betterleaks trailer check" + echo + + if [ "${missing_count}" -eq 0 ]; then + echo "> [!TIP]" + echo "> All **${#commits[@]}** commit(s) in this pull request contain \`betterleaks-Scan: passed\`." + else + echo "> [!WARNING]" + echo "> **${missing_count} commit(s)** do not contain a valid \`betterleaks-Scan: passed\` trailer and need to be scanned again. This is informational and does not fail the workflow." + echo + echo "| Commit | Type | Subject |" + echo "| --- | --- | --- |" + + for index in "${!missing_shas[@]}"; do + sha="${missing_shas[$index]}" + subject="${missing_subjects[$index]//|/\\|}" + echo "| [\`${sha:0:12}\`](${repository_url}/commit/${sha}) | ${missing_types[$index]} | ${subject} |" + done + + echo + echo "## How to fix" + echo + echo "Rewriting commits changes their SHA. Coordinate with other contributors first, then push with \`git push --force-with-lease\`." + echo + echo "1. Make sure this repository's Betterleaks hooks are enabled:" + echo + echo ' ```bash' + echo ' git config --global core.hooksPath .githooks' + echo ' git config --global --get core.hooksPath' + echo ' ```' + echo + echo "2. For missing regular commits, start an interactive rebase:" + echo + echo ' ```bash' + echo ' git fetch origin' + echo " git rebase -i origin/${base_ref}" + echo ' ```' + echo + echo " Change \`pick\` to \`edit\` for every affected regular commit. Each time rebase stops, run:" + echo + echo ' ```bash' + echo ' git commit --amend --no-edit' + echo ' git rebase --continue' + echo ' ```' + echo + echo "3. If an affected commit is a merge commit, preserve merges during the rebase:" + echo + echo ' ```bash' + echo " git rebase -i --rebase-merges origin/${base_ref}" + echo ' ```' + echo + echo " In the rebase todo, insert a line containing \`break\` immediately after the affected \`merge -C ...\` line. When rebase stops after recreating that merge commit, run:" + echo + echo ' ```bash' + echo ' git commit --amend --no-edit' + echo ' git rebase --continue' + echo ' ```' + fi + } >> "${GITHUB_STEP_SUMMARY}" + + if [ "${missing_count}" -gt 0 ]; then + echo "::warning title=Betterleaks scan required::${missing_count} commit(s) are missing a valid betterleaks-Scan: passed trailer. See the Job Summary for commit details and remediation steps." fi trivy-scan: From d3eac0fa0fae22ab9e785d048c0b48b3c2af2f71 Mon Sep 17 00:00:00 2001 From: linhchi Date: Mon, 24 Aug 2026 11:25:55 +0700 Subject: [PATCH 2/3] fix: make workflow fail if missing trailer betterleaks-Scan: passed --- .github/workflows/scan-secret.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scan-secret.yml b/.github/workflows/scan-secret.yml index f467dda..2be359e 100644 --- a/.github/workflows/scan-secret.yml +++ b/.github/workflows/scan-secret.yml @@ -20,7 +20,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - - name: Report commits missing betterleaks trailer + - name: Validate betterleaks trailer run: | set -euo pipefail @@ -77,7 +77,7 @@ jobs: echo "> All **${#commits[@]}** commit(s) in this pull request contain \`betterleaks-Scan: passed\`." else echo "> [!WARNING]" - echo "> **${missing_count} commit(s)** do not contain a valid \`betterleaks-Scan: passed\` trailer and need to be scanned again. This is informational and does not fail the workflow." + echo "> **${missing_count} commit(s)** do not contain a valid \`betterleaks-Scan: passed\` trailer and need to be scanned again. This check fails until every commit has the required trailer." echo echo "| Commit | Type | Subject |" echo "| --- | --- | --- |" @@ -130,7 +130,8 @@ jobs: } >> "${GITHUB_STEP_SUMMARY}" if [ "${missing_count}" -gt 0 ]; then - echo "::warning title=Betterleaks scan required::${missing_count} commit(s) are missing a valid betterleaks-Scan: passed trailer. See the Job Summary for commit details and remediation steps." + echo "::error title=Betterleaks scan required::${missing_count} commit(s) are missing a valid betterleaks-Scan: passed trailer. See the Job Summary for commit details and remediation steps." + exit 1 fi trivy-scan: From 1ab10e596e8c9de7a64b9d3b2ebfc5abd41bcaa7 Mon Sep 17 00:00:00 2001 From: linhchi Date: Mon, 24 Aug 2026 16:58:18 +0700 Subject: [PATCH 3/3] fix: add more description for check trailer job summary betterleaks-Scan: passed --- .github/workflows/scan-secret.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/scan-secret.yml b/.github/workflows/scan-secret.yml index 2be359e..c1d1c87 100644 --- a/.github/workflows/scan-secret.yml +++ b/.github/workflows/scan-secret.yml @@ -88,6 +88,14 @@ jobs: echo "| [\`${sha:0:12}\`](${repository_url}/commit/${sha}) | ${missing_types[$index]} | ${subject} |" done + echo + echo "## How it works" + echo + echo "Eacgh repository includes Betterleaks Git hooks in \`.githooks\`. Enable them by configuring Git's \`core.hooksPath\` to use that directory." + echo + echo "Before each commit, the \`pre-commit\` hook runs Betterleaks against the staged changes. If the scan passes, the \`prepare-commit-msg\` hook adds the \`betterleaks-Scan: passed\` trailer to the commit message as proof that the scan ran successfully. If Betterleaks detects a secret, the commit is blocked." + echo + echo "A commit without the required trailer was created without a successful hook scan, usually because the hooks were not enabled when that commit was made. The affected commits must therefore be replayed and amended after the hooks are enabled, causing Betterleaks to scan them and add the trailer." echo echo "## How to fix" echo