Skip to content

chore: add gitleaks (CI job + pre-commit hook)#9

Merged
timzsu merged 3 commits into
mainfrom
zsu/gitleaks
Apr 30, 2026
Merged

chore: add gitleaks (CI job + pre-commit hook)#9
timzsu merged 3 commits into
mainfrom
zsu/gitleaks

Conversation

@timzsu
Copy link
Copy Markdown
Collaborator

@timzsu timzsu commented Apr 30, 2026

Purpose

Add gitleaks to catch committed secrets at two layers:

  1. Pre-commit hook — runs locally on every 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.
  2. CI job — runs the gitleaks binary over the full git history on every PR and push to 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 a gitleaks job alongside the existing zizmor job. The job downloads the gitleaks v8.30.1 binary at run time and invokes gitleaks detect --source . --no-banner against the checkout. Checkout uses fetch-depth: 0 so the binary sees the full commit graph (without it, the scan is shallow and misses older history). Inherits the workflow-level permissions: contents: read.
  • .pre-commit-config.yaml — adds the gitleaks pre-commit hook, SHA-pinned to gitleaks v8.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 list gitleaks alongside isort/black/ruff/mypy/codespell so the docs match what pre-commit run --all-files actually 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 without pre-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 paid GITLEAKS_LICENSE secret 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 the zizmor job 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

uv run python -c "import yaml; [yaml.safe_load(open(f)) for f in ['.github/workflows/security.yml', '.pre-commit-config.yaml']]"

# Confirm the new gitleaks job doesn't introduce zizmor findings
uvx --from zizmor==1.24.1 zizmor --persona pedantic .github/workflows

# Run the new pre-commit hook against the full tree
uv run pre-commit run gitleaks --all-files

Test Result

  • YAML parses across both touched files.
  • zizmor --persona pedanticNo findings to report. Good job! (8 suppressed). The 8 suppressed are zizmor's auditor-only self-hosted-runner audits, one per job (now 8 with gitleaks added). No project-side suppressions.
  • pre-commit run gitleaks --all-filesDetect hardcoded secrets...........Passed. Zero secrets in the current tree.

Pre-submission Checklist
  • I have read CONTRIBUTING.md (or AGENTS.md if no CONTRIBUTING.md).
  • I have run uv run pre-commit run --all-files and fixed any issues.
  • I have added or updated tests covering my changes (if applicable).
  • I have verified that the test suite passes locally.
  • If this is a breaking change, I have prefixed the PR title with [BREAKING] and described migration steps above.

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>
@timzsu timzsu requested a review from kaiitunnz April 30, 2026 13:42
Copy link
Copy Markdown
Collaborator

@kaiitunnz kaiitunnz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments.

Comment thread CONTRIBUTING.md Outdated

| Tool | Purpose | Config |
|------|---------|--------|
| [gitleaks](https://github.com/gitleaks/gitleaks) | Committed-secret detection | (built-in rules) |
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting config to - should be more appropriate.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment thread .github/workflows/security.yml Outdated
# 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.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments are too detailed.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Condensed.

* ``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>
@timzsu timzsu requested a review from kaiitunnz April 30, 2026 14:02
Copy link
Copy Markdown
Collaborator

@kaiitunnz kaiitunnz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@timzsu timzsu merged commit abab043 into main Apr 30, 2026
8 checks passed
@timzsu timzsu deleted the zsu/gitleaks branch April 30, 2026 14:05
@timzsu timzsu linked an issue Apr 30, 2026 that may be closed by this pull request
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants