Skip to content

fix(ci): scheduled gitleaks sweep flags unmerged-branch history — scope to main + require per-PR secret check #721

Description

@scottschreckengaust

Problem

The scheduled security suite (.github/workflows/security.yml, weekly cron) runs //:security:secrets:

gitleaks git . --no-banner --redact

with the runner checked out at fetch-depth: 0. With no --log-opts, gitleaks scans secrets across all reachable git objects from every fetched ref — not just main. So a secret in an unmerged, no-PR branch's history fails the mainline scheduled suite, even though it never reached main.

Confirmed instance (main @ 3a5b4cb, 2026-08-05)

gitleaks git . --no-banner --redact               → leaks found: 4
gitleaks git . --no-banner --redact --log-opts=HEAD → no leaks found

All 4 findings are the same rule+file: aws-account-id in docs/design/AGENTCORE_GATEWAY_MCP_SPIKE.md, in commits 6c0cf601 / d773e3eb that live only on origin/feat/agentcore-gateway-mcp (a 381-commit spike branch, no PR ever opened, file absent from main). It is a bare 12-digit AWS account ID in a design doc — not a live credential.

This is the residual half of the split fixed by #335/#336 (which scoped the PR/merge_group gitleaks scan to the commit range via security:secrets:range + GITLEAKS_RANGE). The scheduled full-sweep was left unscoped — same class of bug, other surface. Lineage: #327 (P0 "make the merge gate enforceable"), #330 (required fast PR scans), #335/#336 (merge_group range scoping).

Why this matters

  • A branch someone "messes up" (or abandons) can redden the mainline scheduled suite indefinitely, generating noise and auto-filed failure issues (e.g. Security suite failed (main @ db52d5f) #593) that have nothing to do with main.
  • It trains reviewers to ignore a red security suite — the worst outcome for a security gate.

Requirements

Part 1 — scope the scheduled sweep to main's own history.

  • In mise.toml, change //:security:secrets from gitleaks git . --no-banner --redact to scan only history reachable from the mainline, e.g.:
    gitleaks git . --no-banner --redact --log-opts="--first-parent main"
    
    (--first-parent main or HEAD both restrict to the checked-out mainline; prefer an explicit, documented choice.)
  • Keep //:security:secrets:range (per-PR) and //:security:secrets:staged (pre-commit) unchanged.

Part 2 — make the per-PR secret scan a REQUIRED status check.

  • Ensure the range-scoped secret scan (security-pr.yml → "Secret scan (gitleaks, range-scoped)") is a required check in the main branch protection / ruleset so a leak introduced in a PR's own diff blocks merge.
  • Verify interaction with the merge queue (repo uses merge_queue + required pull_request review): the required check must be enforced on the queue entry, not just the PR head.

Gotcha / correctness caveat (LOAD-BEARING — both parts ship together)

Scoping the scheduled sweep to main-only means a secret sitting only in unmerged branch history is no longer caught by the scheduled sweep. That is acceptable only because Part 2 guarantees secrets are caught at introduction on the PR range-scan. Do not land Part 1 without Part 2 — together they move detection to the right place (merge time, on the actual diff) without the false-positive drag of unrelated branches. Note the leak commit above is in origin/main..branch, so if that branch ever opens a PR the range-scan will correctly flag it — which is the intended behavior.

Optional (owner action, not required by this issue)

The feat/agentcore-gateway-mcp branch owner may delete the stale no-PR spike branch to clear the current noise. Do NOT force-rewrite the branch (it is 381 commits, not the reporter's work); deletion is recoverable and appropriate, an in-place history rewrite is not. This issue's mechanism fix makes branch cleanup optional rather than necessary.

Acceptance criteria

  • mise run security:secrets (scheduled task) reports no leaks on main @ current tip (the 4 unmerged-branch findings no longer fail it).
  • A PR that adds a secret to its own diff fails the required per-PR gitleaks check and cannot merge / cannot pass the merge queue.
  • No change to the pre-commit (:staged) or per-PR range (:range) task behavior beyond making the PR check required.
  • Docs: a one-line note in the security:secrets task comment explaining the main-scope decision and pointing here.

References

#327, #330, #335, #336 (lineage); #593 (the failure symptom this removes); ADR-003 (governance).

Metadata

Metadata

Labels

P1medium priorityapprovedWhen an issue has been approved and readyci-cdBuild pipeline, deploy.yml, CI perf/caching, GitHub Actions workflowssecurityCedar/HITL, IAM least-privilege, secrets, PII/DLP, guardrails, supply-chain/CVE

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions