Skip to content

Commit 24db7ad

Browse files
committed
security(ci): verify gitleaks release checksum
1 parent 3e1cb0d commit 24db7ad

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

.github/workflows/security-audit.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,12 @@ jobs:
230230
set -euo pipefail
231231
curl -sSfL -o /tmp/gitleaks.tar.gz \
232232
https://github.com/gitleaks/gitleaks/releases/download/v8.30.0/gitleaks_8.30.0_linux_x64.tar.gz
233+
# Official v8.30.0 release checksum. Verify before extracting or
234+
# executing any downloaded byte; a version-pinned URL alone does not
235+
# authenticate an asset that was replaced or corrupted in transit.
236+
printf '%s %s\n' \
237+
'79a3ab579b53f71efd634f3aaf7e04a0fa0cf206b7ed434638d1547a2470a66e' \
238+
/tmp/gitleaks.tar.gz | sha256sum -c -
233239
tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks
234240
/tmp/gitleaks version
235241

tests/test-security-scan-coverage.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ for step in job.get('steps') or []:
9191
# summarise or upload its output.
9292
_PY_SCAN_STEP="$(_step python-audit 'pip-audit every requirements file')"
9393
_PY_ASSERT_STEP="$(_step python-audit 'Assert the audit actually produced')"
94+
_SECRET_INSTALL_STEP="$(_step secret-scan 'Install gitleaks')"
9495
_SECRET_SCAN_STEP="$(_step secret-scan 'gitleaks scan')"
9596
_SECRET_ASSERT_STEP="$(_step secret-scan 'Assert the secret scan completed cleanly')"
9697
_SAST_ASSERT_STEP="$(_step sast 'Assert CodeQL SARIF and reject unreviewed critical findings')"
@@ -218,6 +219,27 @@ printf '%s' "$_SECRET_RUNS" | grep -qE "gitleaks/releases/download/v[0-9]" \
218219
&& ok "gitleaks version is pinned" \
219220
|| bad "gitleaks is unpinned -- the baseline can move without a commit"
220221

222+
# Pinning the URL is not enough: a replaced or corrupted release asset would
223+
# otherwise be extracted and executed with no byte-level provenance check. The
224+
# digest is the official v8.30.0 linux_x64 release checksum, and verification
225+
# must happen before extraction so no unauthenticated binary reaches /tmp.
226+
_gitleaks_linux_x64_sha="79a3ab579b53f71efd634f3aaf7e04a0fa0cf206b7ed434638d1547a2470a66e"
227+
_gitleaks_checksum_order="$( _LOKI_BODY="$_SECRET_INSTALL_STEP" \
228+
_LOKI_SHA="$_gitleaks_linux_x64_sha" python3 -c "
229+
import os
230+
body = os.environ['_LOKI_BODY']
231+
sha = os.environ['_LOKI_SHA']
232+
verify = body.find(sha)
233+
extract = body.find('tar -xzf /tmp/gitleaks.tar.gz')
234+
print('ok' if verify >= 0 and 'sha256sum -c' in body[verify:extract]
235+
and extract > verify else 'missing')
236+
" 2>/dev/null )"
237+
if [ "$_gitleaks_checksum_order" = "ok" ]; then
238+
ok "gitleaks archive matches the pinned official SHA-256 before extraction"
239+
else
240+
bad "gitleaks archive is executed without the pinned official pre-extraction checksum"
241+
fi
242+
221243
# --- 8. Secret findings block outside an exact reviewed baseline ------------
222244
_secret_name="$( _LOKI_WF="$WF" python3 -c "
223245
import os, yaml

0 commit comments

Comments
 (0)