From ca8c5efc229aa6586c4e058969ea51836f2b7da2 Mon Sep 17 00:00:00 2001 From: codex Date: Wed, 10 Jun 2026 07:26:10 +0000 Subject: [PATCH] docs(prd): add gitleaks allow supervision --- ...gitleaks-inline-suppression-supervision.md | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docs/prds/prd-new-gitleaks-inline-suppression-supervision.md diff --git a/docs/prds/prd-new-gitleaks-inline-suppression-supervision.md b/docs/prds/prd-new-gitleaks-inline-suppression-supervision.md new file mode 100644 index 0000000..276828d --- /dev/null +++ b/docs/prds/prd-new-gitleaks-inline-suppression-supervision.md @@ -0,0 +1,101 @@ +# 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 `.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.