gitleaks tutorial: install, scan, and gate secrets in CI
To use gitleaks, install it with brew, Docker, or a release binary, then run gitleaks git to scan a repository, gitleaks dir to scan files, or pipe data to gitleaks stdin. Tune detection in a .gitleaks.toml, add a pre-commit hook, and gate CI with the official GitHub Action.
Independent SEO consultant & AI practitioner who builds and tests these tools.
gitleaks tutorial: install, scan, and gate secrets in CI
To use gitleaks, install it with brew, Docker, or a release binary, then run gitleaks git to scan a repository, gitleaks dir to scan files, or pipe data to gitleaks stdin. Tune detection in a .gitleaks.toml, add a pre-commit hook, and gate CI with the official GitHub Action. This guide walks each step with real commands verified against the gitleaks repo.
TL;DR:
- Install:
brew install gitleaks, the Docker imageghcr.io/gitleaks/gitleaks:latest, or a binary from the releases page. - Scan:
gitleaks gitfor history,gitleaks dirfor files on disk,gitleaks stdinfor piped input. - Configure: a
.gitleaks.tomlcontrols custom rules, allowlists, and entropy thresholds. - Gate: add a pre-commit hook locally and the
gitleaks/gitleaks-actionin CI. - For tool choice, see gitleaks vs TruffleHog. If a scan finds something, follow committed a secret to GitHub.
How do you install gitleaks?
gitleaks is a single Go binary, so installation is light. Pick whichever route fits your machine:
- Homebrew (macOS or Linux): run
brew install gitleaks. - Docker: pull and run
docker run -v "$(pwd):/path" ghcr.io/gitleaks/gitleaks:latest dir /path. The DockerHub mirrorzricethezav/gitleaks:latestalso works. - Binary: download the archive for your platform from the releases page, extract it, and put
gitleakson yourPATH. - From source:
git clone https://github.com/gitleaks/gitleaks.git, thencd gitleaks && make build.
Confirm it works with gitleaks version. Note that the maintainer has marked gitleaks feature complete, so future releases are security patches only, per the gitleaks documentation. The tool is mature and stable, which is exactly what you want from a secret-scanning gate.
How do you run a scan?
gitleaks has three main scan commands. The older detect and protect commands still function but are hidden, so prefer the current names.
Scan git history:
gitleaks git .
This runs git log -p under the hood and inspects every patch in history, which is how secrets in long-deleted commits get caught.
Scan files on disk:
gitleaks dir .
The dir command, aliased as files and directory, scans the current working tree without touching git history. Use this for non-git folders or build artefacts.
Scan piped input:
cat config.env | gitleaks stdin
stdin reads a stream, which is handy for scanning generated output or a single file inline.
Useful flags across commands include --config/-c to point at a config file, --report-format (json, csv, junit, sarif, or template), --report-path to save the report, --redact to mask secrets in output, and --baseline-path to ignore findings already recorded in a baseline report. A typical CI-friendly run is gitleaks git . --report-format json --report-path gitleaks-report.json --redact.
How do you read the output?
When gitleaks finds a candidate, it prints a finding block with the rule that matched, the secret (redacted if you pass --redact), the file, the commit and author, the line number, and a fingerprint. The fingerprint is the stable identifier you copy into a .gitleaksignore file when you have confirmed a finding is a false positive. By default gitleaks exits 0 when clean and 1 when it finds leaks or hits an error, which is what lets it gate a pipeline.
How do you configure gitleaks with .gitleaks.toml?
gitleaks ships a strong default rule set, but a .gitleaks.toml in your repo root lets you extend it, add custom rules, tune entropy, and silence noise. A minimal config that keeps the defaults and adds one custom rule looks like this:
title = "Custom gitleaks config"
[extend]
useDefault = true
[[rules]]
id = "internal-api-token"
description = "Internal service token"
regex = '''intsvc_[0-9a-zA-Z]{32}'''
entropy = 3.5
keywords = ["intsvc_"]
tags = ["token", "internal"]
[[allowlists]]
description = "Ignore test fixtures and the config itself"
paths = ['''gitleaks\.toml''', '''(.*?)test(.*?)''']
regexes = ['''EXAMPLE_FAKE_KEY''']
stopwords = ['''example''', '''sample''']
Key pieces, all verified against the repo:
[extend]withuseDefault = truekeeps the built-in rules and layers yours on top. You can alsodisabledRules = ["generic-api-key"]to drop a noisy default.[[rules]]defines a custom detector.regexis the pattern,entropysets a minimum randomness threshold so low-entropy matches are skipped, andkeywordspre-filter lines for speed.[[allowlists]]suppresses false positives bypaths,regexes,stopwords, orcommits. You can scope an allowlist to a single rule with[[rules.allowlists]], and targetmatch,secret, orlineviaregexTarget.
Configuration precedence runs from the --config flag, then the GITLEAKS_CONFIG environment variable, then a .gitleaks.toml in the target, and finally the built-in default.
How do you add a pre-commit hook?
The cleanest local gate uses the pre-commit framework. Add this to .pre-commit-config.yaml:
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.2
hooks:
- id: gitleaks
Then run pre-commit install. Now every commit is scanned before it lands, and a finding blocks the commit. If you genuinely need to bypass it once, the documentation supports SKIP=gitleaks git commit. Pin rev to a real release tag and bump it deliberately. For more on this pattern, see secret scanning in pre-commit hooks.
How do you gate CI with the GitHub Action?
For a server-side gate, use the official gitleaks/gitleaks-action. A minimal workflow scans every push and pull request:
name: gitleaks
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
The fetch-depth: 0 is important: it pulls full history so the scan can inspect old commits, not just the latest. The action fails the job when it finds a leak, giving you a hard CI gate. If you prefer to run the binary directly in any CI system, call gitleaks git . --report-format sarif --report-path results.sarif, and rely on the default exit code 1 to fail the step. Adjust failure behaviour with --exit-code if your pipeline needs different semantics.
How do you scan the full history or a commit range?
gitleaks git already covers history by default. To widen or narrow the range, pass --log-opts, which forwards options straight to git log. For example, gitleaks git . --log-opts="--all" scans every branch, while gitleaks git . --log-opts="commitA..commitB" checks a specific range. This is the same engine used by the GitHub Action, so local and CI results match.
Where to go next
gitleaks is detection, not remediation. A committed secret is effectively public because it lives in history, so a found key must be rotated, not just deleted. If a scan turns something up, work through committed a secret to GitHub and rotate first. To decide whether gitleaks alone is enough or whether you also want live verification, read gitleaks vs TruffleHog. For more setup walkthroughs, browse the guides library and the tools directory.
Frequently asked questions
How do I install gitleaks?
The quickest routes are Homebrew with brew install gitleaks, a Docker image such as ghcr.io/gitleaks/gitleaks:latest or zricethezav/gitleaks:latest, or a prebuilt binary from the GitHub releases page. You can also build from source with make build.
What is the difference between gitleaks git and gitleaks dir?
gitleaks git scans a local repository's commit history by running git log -p over patches, so it catches secrets buried in old commits. gitleaks dir, aliased as files or directory, scans the current files on disk without reading git history.
How do I make gitleaks scan the full git history?
Running gitleaks git on a repo scans history by default. To control the range, pass --log-opts, for example --log-opts="--all" to cover every branch, or a commit range like commitA..commitB. Per the gitleaks documentation, --log-opts maps to git log.
How do I ignore a false positive in gitleaks?
You have three options: add a # gitleaks:allow comment on the offending line, add the finding's fingerprint to a .gitleaksignore file, or define an allowlist in .gitleaks.toml using paths, regexes, stopwords, or commits.
Does gitleaks fail a CI build when it finds a secret?
Yes. By default gitleaks exits with code 1 when it finds leaks, which fails the step. The official gitleaks/gitleaks-action handles this in GitHub Actions, and you can tune the behaviour with the --exit-code flag.