--- name: secret-scanning-gitleaks description: Detecting + removing leaked credentials with gitleaks 8+. Pre-commit + CI + full history sweep policies. when_to_use: You're on a security mission, or setting up a new repo, or triaging a "did we push a key?" incident. tags: [security, git] --- # Gitleaks workflow Anchored to **gitleaks 8.20+** (2026 line). Detects secrets in the working tree, staged changes, and git history. ## Modes - **`gitleaks protect --staged`** — pre-commit hook. Blocks commits containing secrets. - **`gitleaks detect`** — scans working tree + full history. Use in CI. - **`gitleaks detect --log-opts="--since=2026-01-01"`** — bounded historical sweep for large repos. ## Pre-commit integration ```bash # .pre-commit-config.yaml repos: - repo: https://github.com/gitleaks/gitleaks rev: v8.20.0 hooks: - id: gitleaks ``` ## Config: `.gitleaks.toml` ```toml title = "clawmates gitleaks config" [extend] useDefault = true # start from bundled rules [[rules]] id = "clawmates-internal-token" description = "Our internal service session token pattern" regex = '''cm_svc_[a-f0-9]{64}''' tags = ["clawmates", "token"] [allowlist] description = "Test fixtures that intentionally contain fake secrets" paths = ['''crates/cm-auth/tests/fixtures/.*'''] regexes = ['''sk-ant-api03-TEST[a-zA-Z0-9]+'''] ``` Rules to add per-repo, not global — every codebase has domain-specific token shapes. ## What to do when it fires **On a commit-in-progress:** 1. Don't commit. 2. Rotate the credential immediately (whether you'd have pushed it or not — assume compromised the moment it existed on disk). 3. Remove from the file. Re-attempt. **On a historical hit (already pushed):** 1. Rotate first, panic second. 2. Force-remove from history with `git filter-repo --replace-text` or `bfg-repo-cleaner`. 3. `git push --force` after coordination with everyone with a clone (they'll need to `git reset --hard origin/main` to avoid re-introducing). 4. Notify anyone who might have cached the value (CI logs, artifact registries, error monitoring backends often store request bodies). ## What gitleaks misses - **Base64-encoded secrets.** Add a rule if you use them. - **Split-across-lines secrets** — most rules are single-line regex. - **Secrets in binary files.** Gitleaks skips binaries by default; scan artifacts separately. - **Encrypted-at-rest formats** (age, sops) — encrypted content is opaque to gitleaks; make sure the ENCRYPTED file being in the repo is the intent. ## Integration with the security mission template Runs `gitleaks detect --report-format=json` in the security_scan phase. Each finding becomes a `mission_task`: - `external_id = ` - `title = " at :"` - `status = "created"` The coding phase remediates: rotate + purge + add allowlist entry if a false positive. Emit `COMPLETED: ` when the rotation is confirmed AND the historical removal is deployed. ## Anti-patterns - **Adding a blanket `.gitleaks.toml` allowlist** covering entire directories. Neuters detection. Allowlist specific patterns with justification comments. - **Fixing the secret leak by squashing history without rotating.** The secret was on disk on multiple machines; it's compromised. Rotate first. - **`.gitignore` as your secret defense.** Files can be added by name from the CLI; gitignore only helps `git add .` sweeps.