102 lines
3.8 KiB
Markdown
102 lines
3.8 KiB
Markdown
# PRD prd-new: Gitleaks inline suppression supervision
|
|
|
|
- **Status:** Active
|
|
- **Author:** codex
|
|
- **Created:** 2026-06-10
|
|
- **Issue:** #208
|
|
|
|
## Summary
|
|
|
|
Route every `# gitleaks:allow` inline suppression through the existing
|
|
supervisor approval queue before git-gate forwards a push upstream. The
|
|
annotation remains available for test fixtures and confirmed false positives,
|
|
but it no longer lets an agent silently bypass the gate's secret scan.
|
|
|
|
## Problem
|
|
|
|
Gitleaks supports inline suppression comments. With the default behaviour,
|
|
a pushed line that contains a secret-like value and `# gitleaks:allow` is
|
|
ignored by gitleaks and accepted by git-gate. That is convenient for dummy
|
|
credentials in tests, but it also gives an agent a one-line bypass for a real
|
|
secret. Once the commit lands, the diff alone cannot prove whether the
|
|
suppression was legitimate.
|
|
|
|
## Goals / Success Criteria
|
|
|
|
1. Git-gate continues to run the normal gitleaks scan for every incoming ref.
|
|
2. After the normal scan passes, git-gate runs a second scan with
|
|
`--ignore-gitleaks-allow` and a JSON report so suppressed findings become
|
|
visible.
|
|
3. If that second scan reports no suppressed findings, the push proceeds
|
|
unchanged.
|
|
4. If it reports suppressed findings, git-gate creates a `gitleaks-allow`
|
|
supervisor proposal containing the ref, file path, line number, rule,
|
|
commit, and flagged line for each finding.
|
|
5. The push proceeds only when the supervisor explicitly approves the
|
|
proposal; rejection, malformed responses, missing supervisor configuration,
|
|
and timeout all refuse the push.
|
|
6. The supervisor TUI requires a reason when approving a `gitleaks-allow`
|
|
proposal, so the audit trail records whether the approval was for a test
|
|
fixture or a false positive.
|
|
|
|
## Non-goals
|
|
|
|
- Replacing gitleaks or changing the main secret-detection rule set.
|
|
- Removing support for `# gitleaks:allow`.
|
|
- Automatically classifying fixture files or false positives.
|
|
- Adding new supervisor transport or authentication mechanisms.
|
|
|
|
## Design
|
|
|
|
### Git-gate flow
|
|
|
|
`git_gate_render_hook()` emits a `supervise_gitleaks_allow` shell helper.
|
|
For each incoming ref, git-gate first runs the existing gitleaks command. If
|
|
that scan passes, it runs:
|
|
|
|
```sh
|
|
gitleaks git \
|
|
--log-opts="$log_opts" \
|
|
--no-banner \
|
|
--redact \
|
|
--ignore-gitleaks-allow \
|
|
--report-format=json \
|
|
--report-path="$report_file" \
|
|
--exit-code 0
|
|
```
|
|
|
|
The second pass keeps the push path non-interactive while producing a report
|
|
of findings that would otherwise have been hidden by inline suppression.
|
|
|
|
### Supervisor proposal
|
|
|
|
When the JSON report contains findings, an embedded Python helper writes a
|
|
proposal into `SUPERVISE_QUEUE_DIR` using the existing proposal schema. The
|
|
proposal uses:
|
|
|
|
- `tool: "gitleaks-allow"`
|
|
- a text payload with the ref and each finding's file, line, rule, commit,
|
|
and redacted code line
|
|
- a justification that tells the operator to approve only dummy test fixtures
|
|
or confirmed false positives
|
|
|
|
Git-gate then waits for `<proposal-id>.response.json` for
|
|
`SUPERVISE_GITLEAKS_ALLOW_TIMEOUT_SECONDS`, defaulting to 300 seconds.
|
|
`approved` and `modified` responses allow the push; `rejected`, invalid
|
|
responses, invalid timeout configuration, or timeout refuse it.
|
|
|
|
### Supervisor UI
|
|
|
|
`TOOL_GITLEAKS_ALLOW` is added to the supervisor tool registry. The curses
|
|
supervisor renders the proposal as text and allows approval or rejection.
|
|
Modification is unavailable for this proposal type because there is no file
|
|
patch to apply. Approval from the TUI prompts for a non-empty reason and
|
|
writes that reason to the response/audit path.
|
|
|
|
### Tests
|
|
|
|
Unit tests assert that the rendered git-gate hook includes the second gitleaks
|
|
pass, supervisor queue fields, and fail-closed messages. Supervisor tests cover
|
|
the new tool constant, proposal archiving, and the required TUI approval
|
|
reason.
|