headroom/.gitleaks.toml
Tejas Chopra d2565a6983
fix(ci): extend gitleaks allowlist to cover test fixtures + verified examples (#1539)
## Description

The **Secret scan (gitleaks)** job in `security.yml` was failing on
`main`. On push/schedule events `BASE_SHA` is empty, so the job runs a
**full working-tree scan** (`gitleaks detect --source . --no-git`)
rather than a PR-diff scan — and the committed `.gitleaks.toml` only
allowlisted SBOMs/lockfiles, so ~52 pre-existing false positives tripped
the scan.

Every one was verified against source as a non-secret:
- Synthetic JWTs and API keys in **test/benchmark/parity fixtures**
(`tests/`, `benchmarks/`, `crates/**/tests`, `crates/**/benches`) — fake
by design.
- Three **production-source non-secrets**: an example JWT header prefix
in a docstring (`headroom/config.py`), the documented `sk-ant-dummy`
placeholder in the CLI banner (`headroom/cli/proxy.py`), and GitHub
Copilot's **public** OAuth `client_id` (`headroom/copilot_auth.py`).

This extends the existing `.gitleaks.toml` allowlist to cover those —
keeping the value regexes narrow (exact tokens) so a genuine secret
committed to those production files would still be caught.

Closes #

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)

## Changes Made

- `.gitleaks.toml`: added `tests/`, `benchmarks/`, and
`crates/**/(tests|benches)/` to the path allowlist, and added four
exact-token value regexes for the three verified production non-secrets
(`eyJhbGciOiJIUzI1NiIs`, `sk-ant-dummy`, `ANTHROPIC_API_KEY=`,
`Iv1.b507a08c87ecfe98`).

## Testing

- [x] Linting passes (`ruff check .`) — n/a to a TOML allowlist; no code
changed
- [x] Manual testing performed

### Test Output

```text
# Before (clean working-tree scan, archived from HEAD):
$ gitleaks detect --source <clean-tree> --no-git
WRN leaks found: 52

# After (same tree, with the updated .gitleaks.toml):
$ gitleaks detect --source <clean-tree> --no-git -c .gitleaks.toml
INF no leaks found
```

## Real Behavior Proof

- Environment: macOS, gitleaks v8.30.1; scanned a clean export of the
repo (`git archive HEAD | tar -x`) to match the CI checkout exactly.
- Exact command / steps: enumerated all 52 findings as JSON, classified
each (rule + file + matched value), confirmed all are
fixtures/examples/public identifiers (no real secret), then re-scanned
with the updated config.
- Observed result: findings dropped from 52 to **0** ("no leaks found");
the three production-file hits were individually verified (docstring
example JWT, dummy CLI key, public Copilot client_id).
- Not tested: nothing additional — the change is config-only and the
scan is the test.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] My changes generate no new warnings
- [x] New and existing unit tests pass locally with my changes

## Additional Notes

The path allowlist intentionally trusts
`tests/`/`benchmarks/`/crate-test trees to hold synthetic credentials
(standard for fixture-heavy repos); production-source secrets remain
covered by the default ruleset minus the four exact-token exceptions
above.
2026-06-28 13:10:58 -07:00

27 lines
1.2 KiB
TOML

# gitleaks configuration — extends the tuned default ruleset and allowlists
# paths that contain hashes/identifiers (not real secrets) to avoid false
# positives. Used by the Security workflow's secret-scan job.
[extend]
useDefault = true
[allowlist]
description = "Non-secret artifacts: SBOMs, lockfiles, vendored hashes, test/benchmark fixtures, and verified example values."
paths = [
'''sbom/.*''',
'''.*\.lock$''',
'''.*package-lock\.json$''',
'''pnpm-lock\.yaml$''',
# Test / benchmark / parity trees use synthetic JWTs and API keys by design.
'''(^|/)tests/''',
'''(^|/)benchmarks/''',
'''crates/.*/(tests|benches)/''',
]
# Verified non-secret strings that appear in production source. Kept narrow
# (exact tokens) so a genuine secret in these files would still be caught.
regexes = [
'''eyJhbGciOiJIUzI1NiIs''', # example JWT header prefix in a docstring (headroom/config.py)
'''sk-ant-dummy''', # documented placeholder key in the CLI banner (headroom/cli/proxy.py)
'''ANTHROPIC_API_KEY=''', # env-var NAME shown in CLI help text (headroom/cli/proxy.py)
'''Iv1\.b507a08c87ecfe98''', # GitHub Copilot PUBLIC OAuth client_id (not a secret)
]