-
Notifications
You must be signed in to change notification settings - Fork 2.4k
207 lines (187 loc) · 8.13 KB
/
scan-secrets.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
---
name: Scan for secret leaks and changes
on:
# Block PR modification of workflow
pull_request_target:
push:
workflow_dispatch:
# N/B: Default write-all permission for pull_request_target
permissions: read-all
env:
# How far back in history to go when scanning a branch/tag
# This is most significant when scanning vs new release-branches
# with commit IDs that may differ from those encoded in the
# .gitleaks/baseline.json data (which always comes from
# the default branch).
# TODO: Is there any way to not hard-code this?
# N/B: This value is reused by Cirrus-CI, see contrib/cirrus/prebuild.sh
brdepth: 50
# GitLeaks container image to use.
# N/B: Updating this is hard to test, esp. care must be exercised re: new leak-ignore behaviors
# (example ref: 'Check for inline scan overrides' step below). Also b/c this workflow is not
# intended to be used with the 'pull_request' trigger - as doing so defeats gitleaks scan
# result trustworthiness.
# N/B: This value is reused by Cirrus-CI, see contrib/cirrus/prebuild.sh
glfqin: ghcr.io/gitleaks/gitleaks@sha256:e5f6d1a62786affd1abd882ecc73e9353ce78adea1650711f6e351767723712d # v8.18.0
# General arguments to pass for all execution contexts
# Ref: https://github.com/gitleaks/gitleaks#usage
# N/B: This value is reused by Cirrus-CI, see contrib/cirrus/prebuild.sh
glargs: >-
--exit-code=1
--no-banner
--verbose
--log-level=debug
--source=/subject
--config=/default/.gitleaks.toml
--report-path=/report/gitleaks-report.json
--baseline-path=/default/.gitleaks/baseline.json
# Where to send notification e-mail
RCPTCSV: [email protected]
jobs:
scan-secrets:
runs-on: ubuntu-latest
env:
# Reduce duplication & command-line length
gitlogcmd: "git -C ${{ github.workspace }}/_subject log -p -U0"
steps:
- name: Define git log command and options for re-use
id: gitlog
shell: bash
run: |
set -exuo pipefail
if [[ "${{ github.base_ref }}" == "" ]]; then # It's a branch/tag
echo "range=-${{ env.brdepth }}" >> $GITHUB_OUTPUT
else # It's a PR
echo "range=${{ github.event.pull_request.head.sha }}~${{ github.event.pull_request.commits }}..HEAD" >> $GITHUB_OUTPUT
fi
# On a large repo, there's no need to check out the entire thing. For PRs
# the depth can be limited to one-greater than the number of PR commits.
# Unfortunately, GHA is incapable of performing simple math in-line.
- name: Do some simple math for PR clone depth
if: github.base_ref != ''
id: one_more_commit
shell: bash
run: |
echo "depth=$((${{ github.event.pull_request.commits }} + 1))" >> $GITHUB_OUTPUT
- name: Show important context details
shell: bash
run: |
set -euo pipefail
echo "The workspace path is '${{ github.workspace }}'"
echo "The github.base_ref value is '${{ github.base_ref }}'"
echo "The branch scan depth value is '${{ env.brdepth }}'"
echo "The PR clone depth value is '${{ steps.one_more_commit.outputs.depth }}'"
echo "The gitlogcmd value is '${{ env.gitlogcmd }}'"
echo "The gitlog range value is '${{ steps.gitlog.outputs.range }}'"
echo "The GitLeaks container FQIN is '${{ env.glfqin }}'"
echo "::group::The trigger event JSON"
jq --color-output --indent 2 --sort-keys . $GITHUB_EVENT_PATH
echo "::endgroup::"
# N/B: Use "_" prefixed paths to (somewhat) guard against clashes. GHA has some
# non-POLA behaviors WRT `${{ github.workspace }}` + checkout action.
- name: Checkout PR
if: github.base_ref != ''
uses: actions/checkout@v4
with:
persist-credentials: false
path: _subject
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: ${{ steps.one_more_commit.outputs.depth }}
- name: Checkout Branch/Tag
if: github.base_ref == ''
uses: actions/checkout@v4
with:
persist-credentials: false
path: _subject
fetch-depth: ${{ env.brdepth }}
# Trusted source of gitleaks config.
- name: Checkout default branch
uses: actions/checkout@v4
with:
persist-credentials: false
ref: ${{ github.event.repository.default_branch }}
path: _default
fetch-depth: 1
- name: Create report directory
shell: bash
run: |
set -exuo pipefail
mkdir ${{ github.workspace }}/_report
touch ${{ github.workspace }}/_report/gitleaks-report.json
# A force-push to a PR can obscure Cirrus-CI logs, but not GHA logs
- name: Show content being scanned
shell: bash
run: |
set -exuo pipefail
${{ env.gitlogcmd }} ${{ steps.gitlog.outputs.range }}
# Unfortunately gitleaks provides several in-built ways to
# completely bypass an alert within PR-level commits. Assume
# it's not possible to detect these with gitleaks-config rules.
- name: Check for inline scan overrides
if: github.base_ref != '' # A PR
shell: bash
env:
# Workaround erronously detecting the string in this file
_rx1: "gitleaks"
_rx2: ":"
_rx3: "allow"
run: |
set -euo pipefail
verboten_rx="${_rx1}${_rx2}${_rx3}"
verboten=$(set -x ; ${{ env.gitlogcmd }} "-G$verboten_rx" ${{ steps.gitlog.outputs.range }})
if [[ -n "$verboten" ]]; then
printf '::error::%s' 'Found comment(s) utilizing detection override(s) (see job log for details)'
# Hack: Grep will never colorize an end of a line match
echo "$verboten" | grep --color=always -E "($verboten_rx)|$"
exit 1
fi
if [[ -r "${{ github.workspace }}/_subject/.gitleaksignore" ]]; then
printf '::error::%s' 'Detected a .gitleaksignore file from untrusted source.'
exit 1
fi
- name: Scan for secrets
shell: bash
# gitleaks entrypoint runs as gitleaks user (UID/GID 1000)
run: |
set -exuo pipefail
# TODO: Workaround podman < v4.3.0 support for `--userns=keep-id:uid=1000,gid=1000`.
declare -a workaround_args
workaround_args=(\
--user 1000:1000
--uidmap 0:1:1000
--uidmap 1000:0:1
--uidmap 1001:1001:64536
--gidmap 0:1:1000
--gidmap 1000:0:1
--gidmap 1001:1001:64536
)
# Careful: Changes need coordination with contrib/cirrus/prebuild.sh
podman run --rm \
--security-opt=label=disable \
"${workaround_args[@]}" \
-v ${{ github.workspace }}/_default:/default:ro \
-v ${{ github.workspace }}/_subject:/subject:ro \
-v ${{ github.workspace }}/_report:/report:rw \
$glfqin \
detect $glargs --log-opts=${{ steps.gitlog.outputs.range }}
- name: Collect scan report artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3
with:
name: gitleaks-report
path: ${{ github.workspace }}/_report/gitleaks-report.json
# Nobody monitors the actions-tab for failures, and may not see this
# fail on push to a nefarious PR. Send an e-mail alert to unmask
# this activity or some other general job failure.
- if: failure() && !contains(github.event.pull_request.labels.*.name,'BypassLeakNotification')
name: Send leak detection notification e-mail
uses: dawidd6/[email protected]
with:
server_address: ${{secrets.ACTION_MAIL_SERVER}}
server_port: 465
username: ${{secrets.ACTION_MAIL_USERNAME}}
password: ${{secrets.ACTION_MAIL_PASSWORD}}
subject: Addition|Change|Use of sensitive ${{github.repository}}-CI value
to: ${{env.RCPTCSV}}
from: ${{secrets.ACTION_MAIL_SENDER}}
body: "Please investigate: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}"