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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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