Skip to content

decision: scheduled gitleaks sweep — drop it (rely on per-PR range) or scope it to main? (blocks #721) #723

Description

@scottschreckengaust

Decision needed: what to do with the scheduled full-history gitleaks sweep

Blocks/scopes #721. Splitting the decision out from the implementation because there's a real security trade-off that a reviewer/owner should ratify before code lands.

Background — how the three gitleaks tasks are wired today

Surface Task invoked Scope Enforcement
PR gate (security-pr.yml, required check "Secrets, deps, and workflow scan") security:secrets:range commits in origin/$BASE..HEAD (the PR's own diff) Blocks merge (#327/#330)
Scheduled weekly (security.ymlmise run security) security:secrets (full) all fetched refs (runner is fetch-depth: 0) Files a failure issue; does not gate PRs
Local pre-push (hooks:pre-push:securitymise run security) security:secrets (full) all fetched refs Local only

The problem (surfaced in #721 / #593)

The scheduled security:secrets runs bare gitleaks git . --no-banner --redact with no --log-opts, so it scans secrets across every fetched ref — including unmerged, no-PR branches. A stray/abandoned branch (e.g. an AWS account id in a doc on feat/agentcore-gateway-mcp, a 381-commit spike with no PR) reddens the mainline scheduled suite even though nothing reached main. Confirmed empirically:

gitleaks git . --no-banner --redact               → leaks found: 4  (all from an unmerged branch)
gitleaks git . --no-banner --redact --log-opts=HEAD → no leaks found (main history is clean)

The decision

The PR gate already uses the range scan and is a required check — no change needed there. The question is only about the scheduled/pre-push full sweep:

Option 1 — Remove the full sweep; rely solely on the per-PR range scan.

Option 2 — Keep the full sweep, but scope it to the mainline (--log-opts="HEAD").

  • ✅ Retains a full-history backstop over main (verified: scans main's 279-commit history and fail-closes on a planted mainline secret).
  • ✅ Excludes other branches' unmerged history — kills the fix(ci): scheduled gitleaks sweep flags unmerged-branch history — scope to main + require per-PR secret check #721 false-positive class.
  • ✅ One-line change; pre-push still scans the developer's own branch commits.
  • ⚠️ A secret living only in unmerged branch history is no longer caught by the sweep — acceptable because the required per-PR range gate catches it at merge time, on the actual diff (where you want the gate to fire).
  • 🪤 Gotcha discovered while prototyping: scope with HEAD, not a ref-pattern like --remotes=origin/main — the latter matches no ref in a plain worktree and walks 0 commits, silently turning the scan into a fail-open no-op. HEAD always walks the real checked-out history (which is main in the scheduled run).

Recommendation

Option 2. Unlike a redundant pin (where an in-path gate makes a floor pointless), the full sweep is not redundant with the range gate: the range gate is recent and diff-only, so it cannot see main's pre-#330 history or non-PR paths. Option 2 keeps that unique backstop while removing the false-positive drag. Option 1 trades away real coverage for marginal simplicity.

Whichever is chosen, #721 implements it

  • Option 1 → drop security:secrets from the security aggregate (+ pre-push), update docs, note the coverage gap accepted.
  • Option 2 → set security:secrets run to gitleaks git . --no-banner --redact --log-opts="HEAD", comment the rationale + the --remotes fail-open trap, keep :range and :staged unchanged.

Acceptance for THIS issue

References

#721 (implementation), #593 (failure symptom), #327 / #330 (required per-PR range gate), #335 / #336 (prior merge_group range-scoping — the other half of this split), ADR-003 (governance).

Metadata

Metadata

Labels

P1medium priorityci-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