From 43c8bd85df15fe22207391073601149a3dc408c9 Mon Sep 17 00:00:00 2001 From: t Date: Wed, 5 Aug 2026 23:22:48 +0000 Subject: [PATCH] fix(security): scope gitleaks sweep to the mainline via --log-opts=HEAD (#721) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bare `gitleaks git .` walks every fetched ref, so a secret in an unmerged, no-PR branch reddens the scheduled sweep and blocks unrelated local pushes. Scope it to HEAD, per the Option 2 decision ratified in #723. HEAD is deliberate and not interchangeable with `main`: this task backs both the scheduled sweep and the pre-push hook. HEAD resolves to `main` in CI, but in a feature worktree it also covers the commits being pushed — pinning to `main` would skip the developer's own commits and make the pre-push hook a no-op exactly when it should fire. Verified against the real task: clean on the mainline (269 commits), exit 1 on a planted account id in a local commit. `:range` and `:staged` unchanged; the per-PR range scan is already a required check, so #721 Part 2 needs no change. Co-Authored-By: Claude --- mise.toml | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/mise.toml b/mise.toml index 6851e303..73ef2ed4 100644 --- a/mise.toml +++ b/mise.toml @@ -126,11 +126,28 @@ run = [ ################## [tasks."security:secrets"] -description = "Scan all git history for secrets with gitleaks (full-history sweep)" +description = "Scan the checked-out history for secrets with gitleaks (scheduled sweep + pre-push)" # `gitleaks git` (history-aware) replaces the deprecated `gitleaks detect` -# (removed from --help in v8.19.0). With no --log-opts this scans the full -# history reachable from the checkout, matching the previous behaviour. -run = "gitleaks git . --no-banner --redact" +# (removed from --help in v8.19.0). +# +# Scoped to `HEAD` rather than left bare (#721, decision ratified in #723). +# Bare `gitleaks git .` walks EVERY fetched ref, so a secret in an unmerged, +# no-PR branch reddens this scan for everyone — it trains reviewers to ignore a +# red security gate, which is the worst outcome for one. +# +# `HEAD` is deliberate, and is NOT interchangeable with `main` here. HEAD is +# relative: in the scheduled CI run it resolves to `main`, but on pre-push in a +# feature worktree it also covers the commits being pushed. Pinning this to +# `main` would skip the developer's own commits — the pre-push hook would stop +# catching the secret you are about to publish. +# +# Do NOT "scope" this with a ref pattern like `--remotes=origin/main`: that +# matches no ref in a plain worktree, walks 0 commits, and silently turns the +# scan into a fail-OPEN no-op. +# +# Secrets introduced by a PR are independently caught at merge time by the +# required range-scoped check (`security:secrets:range`, see security-pr.yml). +run = 'gitleaks git . --no-banner --redact --log-opts="HEAD"' [tasks."security:secrets:range"] description = "gitleaks over a commit range only (per-PR gate). Set GITLEAKS_RANGE, e.g. origin/main..HEAD"