Skip to content

Commit 3073275

Browse files
committed
Update Betterleaks email notification
1 parent daca3cf commit 3073275

2 files changed

Lines changed: 98 additions & 0 deletions

File tree

.github/workflows/betterleaks.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ jobs:
1111
scan:
1212
name: Scan for secrets
1313
runs-on: ubuntu-latest
14+
env:
15+
SMTP_URL: ${{ secrets.SMTP_URL }}
16+
SMTP_PORT: ${{ secrets.SMTP_PORT || '25' }}
17+
SMTP_EMAIL: ${{ secrets.SMTP_EMAIL }}
18+
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
1419
steps:
1520
- name: Checkout repository
1621
uses: actions/checkout@v4
1722
with:
1823
fetch-depth: 1
24+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
1925

2026
- name: Run Betterleaks
2127
id: betterleaks
@@ -41,6 +47,85 @@ jobs:
4147
path: betterleaks-report.json
4248
if-no-files-found: ignore
4349

50+
- name: Build Betterleaks email summary
51+
id: leak_summary
52+
if: steps.betterleaks.outcome == 'failure'
53+
shell: bash
54+
run: |
55+
if [[ -s betterleaks-report.json ]]; then
56+
jq -r '
57+
def one_line:
58+
tostring
59+
| gsub("[\r\n]+"; " ")
60+
| if length > 240 then .[0:240] + "..." else . end;
61+
62+
.[:20][]
63+
| "- " + (.RuleID // "unknown-rule")
64+
+ " at " + (.File // "unknown-file")
65+
+ ":" + ((.StartLine // 0) | tostring)
66+
+ "\n match: " + ((.Match // .Secret // "REDACTED") | one_line)
67+
' betterleaks-report.json > betterleaks-email-summary.txt
68+
69+
count="$(jq 'length' betterleaks-report.json)"
70+
if (( count > 20 )); then
71+
{
72+
echo ""
73+
echo "... and $((count - 20)) more finding(s). Download the artifact for full details."
74+
} >> betterleaks-email-summary.txt
75+
fi
76+
else
77+
echo "No JSON report was generated. Download the workflow logs for details." > betterleaks-email-summary.txt
78+
fi
79+
80+
{
81+
echo "text<<BETTERLEAKS_SUMMARY"
82+
cat betterleaks-email-summary.txt
83+
echo "BETTERLEAKS_SUMMARY"
84+
} >> "$GITHUB_OUTPUT"
85+
86+
- name: Resolve committer email
87+
id: committer
88+
if: steps.betterleaks.outcome == 'failure'
89+
shell: bash
90+
run: |
91+
committer_email="$(git log -1 --format='%ce')"
92+
author_email="$(git log -1 --format='%ae')"
93+
email="$committer_email"
94+
if [[ -z "$email" || "$email" == *"noreply.github.com"* ]]; then
95+
email="$author_email"
96+
fi
97+
if [[ "$email" =~ ^[^[:space:]@]+@[^[:space:]@]+\.[^[:space:]@]+$ && "$email" != *"noreply.github.com"* ]]; then
98+
echo "email=$email" >> "$GITHUB_OUTPUT"
99+
else
100+
echo "No deliverable committer email found; skipping Betterleaks email notification."
101+
echo "email=" >> "$GITHUB_OUTPUT"
102+
fi
103+
104+
- name: Email committer on Betterleaks failure
105+
if: steps.betterleaks.outcome == 'failure' && steps.committer.outputs.email != '' && env.SMTP_URL != '' && env.SMTP_EMAIL != ''
106+
uses: dawidd6/action-send-mail@v18
107+
with:
108+
server_address: ${{ env.SMTP_URL }}
109+
server_port: ${{ env.SMTP_PORT }}
110+
secure: ${{ env.SMTP_PORT == '465' }}
111+
username: ${{ env.SMTP_EMAIL }}
112+
password: ${{ env.SMTP_PASSWORD }}
113+
from: ${{ env.SMTP_EMAIL }}
114+
to: ${{ steps.committer.outputs.email }}
115+
subject: "[Betterleaks] Secret scan failed in ${{ github.repository }}"
116+
body: |
117+
Betterleaks detected one or more potential secrets.
118+
119+
Repository: ${{ github.repository }}
120+
Branch: ${{ github.ref_name }}
121+
Commit: ${{ github.sha }}
122+
Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
123+
124+
Findings:
125+
${{ steps.leak_summary.outputs.text }}
126+
127+
Download the betterleaks-report artifact from the workflow run for details.
128+
44129
- name: Fail if Betterleaks found leaks
45130
if: steps.betterleaks.outcome == 'failure'
46131
run: |

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,19 @@ repository content on every push and pull request. The scan uses the rules in
110110
`.gitleaks.toml` and uploads a `betterleaks-report` artifact when a finding is
111111
detected.
112112

113+
If the optional SMTP secrets are configured, failed scans also send an email to
114+
the last commit committer. The workflow expects these repository or
115+
organization secrets:
116+
117+
- `SMTP_URL`
118+
- `SMTP_PORT` (optional, defaults to `25`)
119+
- `SMTP_EMAIL`
120+
- `SMTP_PASSWORD` (optional if the SMTP server does not require authentication)
121+
122+
Port `465` is sent with direct TLS; other ports use the default SMTP handshake.
123+
The email includes a short finding summary from the redacted Betterleaks report,
124+
including the redacted matched line from each finding.
125+
113126
There are three common outcomes:
114127

115128
1. **Everything is OK.** The `Betterleaks / Scan for secrets` check is green and

0 commit comments

Comments
 (0)