From a06416541bc3888d01fae971ec44a92c4710d78c Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Thu, 30 Jul 2026 21:51:56 +0000 Subject: [PATCH] ci(gitleaks): gate PRs on their own commits, pin two more false positives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every PR in this repo failed gitleaks, whatever it touched. The job ran `gitleaks detect --source .` over full history, so it resolved to a blob committed once and reported it forever — #163 and #166 both went red on a finding neither introduced. A check that is red on arrival stops being read, which is the failure mode that matters here. Pull requests now scan only base..head. History is still scanned in full on push to master and on the weekly cron, so an existing finding cannot be merged out of sight — it just stops masking new ones. Two more false-positive fingerprints. A fingerprint pins one commit, and both already-pinned lines survived later edits to their files, so each matched again under a newer SHA: the pk_test_ fixture the analyzer test asserts on, and the docs curl example that by then read `-H "Authorization: Bearer $SECRET"`. Deliberately still unpinned: the 21 findings in .env.bak-2026-07-28. Those are real credentials, they remain in history, and suppressing them before they are rotated would hide a live exposure. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/security.yml | 15 +++++++++++++++ .gitleaksignore | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index cea1dbeb..4989e1b4 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -68,5 +68,20 @@ jobs: curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${VERSION}/gitleaks_${VERSION}_linux_x64.tar.gz" \ | tar -xz -C /usr/local/bin gitleaks gitleaks version + # A pull request is gated on what IT introduces. Scanning full history + # here failed every PR in the repo on the same historical blob, no matter + # what the PR touched — and a check that is red on arrival is a check + # nobody reads. The history is still scanned, on master and on the weekly + # cron below, so a finding cannot be merged out of sight. + - name: Scan pull request commits + if: github.event_name == 'pull_request' + run: | + gitleaks detect --source . --redact --verbose --no-banner --exit-code 1 \ + --log-opts="--no-merges ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}" + + # push to master + schedule: everything, forever. This is what surfaces + # credentials already committed; it stays red until they are rotated and + # the blob is purged from history. - name: Scan history + if: github.event_name != 'pull_request' run: gitleaks detect --source . --redact --verbose --no-banner --exit-code 1 diff --git a/.gitleaksignore b/.gitleaksignore index 022fe367..1d142fb1 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -13,3 +13,14 @@ # tag fixture for the tracker integration analyzer test. Not a real secret — # it's asserted on by the test, so pin the historical blob rather than rewrite. 64a771186801871e191fb913b801b086d9ef3235:tests/contract/tracker-integrations.test.ts:generic-api-key:8 + +# A fingerprint pins one commit, and both lines above survived edits to their +# files, so the same non-secret matches again under every later SHA that still +# carries the line. These are the remaining occurrences of the two entries +# above — same lines, same verdict, later commits. +# +# 2eb14f9b: the same pk_test_ fixture. +2eb14f9b73d3100d207b41ea23d216ee2100acc9:tests/contract/tracker-integrations.test.ts:generic-api-key:8 +# 508859ed: the same curl example, by then reading `-H "Authorization: Bearer +# $SECRET"` — a shell variable the reader substitutes, not a token. +508859ed12ff73cd5044a4fd10971372779578cb:app/(marketing)/docs/autoblog-webhook/page.tsx:curl-auth-header:130