chore: add gitleaks (CI job + pre-commit hook)#9
Merged
Merged
Conversation
Adds a ``gitleaks`` job alongside the existing ``zizmor`` job in ``.github/workflows/security.yml``. The job uses ``gitleaks/gitleaks-action@v2.3.9`` (SHA-pinned) over the full git history (``fetch-depth: 0``). Adds the gitleaks pre-commit hook to ``.pre-commit-config.yaml``, pinned to gitleaks v8.30.1 by SHA. Runs first in the hook chain so a secret blocks the commit before the formatters touch the diff. The two layers play different roles: the pre-commit hook catches secrets before they reach a remote (history rewrites don't undo what was already pulled), the CI job is the safety net for contributors who don't have local pre-commit installed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Zhengyuan Su <su.zhengyuan@u.nus.edu>
CONTRIBUTING.md's "pre-commit hook stages" list and tools-table both gain a gitleaks entry. AGENTS.md's "Hooks:" enumeration matches. The hook is added to ``.pre-commit-config.yaml`` in the same PR; this keeps the docs in sync with what ``pre-commit run --all-files`` actually runs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Zhengyuan Su <su.zhengyuan@u.nus.edu>
kaiitunnz
requested changes
Apr 30, 2026
|
|
||
| | Tool | Purpose | Config | | ||
| |------|---------|--------| | ||
| | [gitleaks](https://github.com/gitleaks/gitleaks) | Committed-secret detection | (built-in rules) | |
Collaborator
There was a problem hiding this comment.
Setting config to - should be more appropriate.
| # Direct binary invocation rather than gitleaks-action: the | ||
| # action requires a paid GITLEAKS_LICENSE for org-owned repos | ||
| # (mlsys-io counts). The binary itself is freely available. | ||
| # Pinned to v8.30.1 to match the pre-commit hook. |
Collaborator
There was a problem hiding this comment.
Comments are too detailed.
* ``security.yml`` — collapse the four-line comment above the gitleaks ``run:`` block into a single line. * ``CONTRIBUTING.md`` — gitleaks's "Config" cell becomes ``-`` (the table convention for tools without a project-side config) instead of the parenthetical I'd written. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Zhengyuan Su <su.zhengyuan@u.nus.edu>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Add
gitleaksto catch committed secrets at two layers:git commit, blocks the commit if a secret is detected. Catches leaks before they reach a remote — once a secret is pulled by anyone, history rewrites don't undo what was already fetched.main. Safety net for contributors without local pre-commit installed, and catches anything the local hook missed (e.g., a force-push that rewrote history but kept the secret).Changes
.github/workflows/security.yml— adds agitleaksjob alongside the existingzizmorjob. The job downloads the gitleaksv8.30.1binary at run time and invokesgitleaks detect --source . --no-banneragainst the checkout. Checkout usesfetch-depth: 0so the binary sees the full commit graph (without it, the scan is shallow and misses older history). Inherits the workflow-levelpermissions: contents: read..pre-commit-config.yaml— adds the gitleaks pre-commit hook, SHA-pinned to gitleaksv8.30.1. Runs first in the chain so a detected secret blocks the commit before any formatter touches the diff.CONTRIBUTING.md,AGENTS.md— the existing "pre-commit hooks" enumeration and tools table listgitleaksalongside isort/black/ruff/mypy/codespell so the docs match whatpre-commit run --all-filesactually runs.Design
Why two layers, not one. Pre-commit catches the leak at the earliest point (before push), but it's per-developer and can be bypassed (
git commit --no-verify, fresh clone withoutpre-commit install, contributors who don't run hooks locally). The CI job is the unconditional fence: every PR, regardless of contributor habits.Why gitleaks rather than trufflehog. Trufflehog's distinguishing feature is credential verification — it tries the discovered secret against the live API to confirm it's still valid, which makes it a better incident-response tool. For pre-merge prevention (the use case here), pattern detection is what matters and gitleaks does it faster with a tighter false-positive profile. We don't need both; running them in parallel produces duplicate findings without new signal.
Why the binary, not
gitleaks/gitleaks-action. The official action requires a paidGITLEAKS_LICENSEsecret for org-owned repos (mlsys-io qualifies); the gitleaks binary itself is freely available and identical to what the action wraps. Same approach used by thezizmorjob in the same workflow (uvx instead of zizmor-action). One pinned version (v8.30.1) covers both the CI binary download and the pre-commit hook so they stay in lockstep.Test Plan
Test Result
zizmor --persona pedantic→No findings to report. Good job! (8 suppressed). The 8 suppressed are zizmor's auditor-onlyself-hosted-runneraudits, one per job (now 8 with gitleaks added). No project-side suppressions.pre-commit run gitleaks --all-files→Detect hardcoded secrets...........Passed. Zero secrets in the current tree.Pre-submission Checklist
CONTRIBUTING.md(orAGENTS.mdif noCONTRIBUTING.md).uv run pre-commit run --all-filesand fixed any issues.[BREAKING]and described migration steps above.