Files
claude/.gitleaks.toml
T
bmottin e59e26890e chore(gitleaks): allowlist Claude Code daemon roster + per-session keys
`make scan-secrets` flagged 4 generic-api-key hits in ~/.claude, all written
by Claude Code itself: roster.json's rendezvousSock/ptySock unix-socket paths
and sessionId UUID (long, high-entropy, not credentials), and two per-worker
session keys (0600). Same class as the ide/*.lock entry above — machine-local,
ephemeral, and unreachable from a commit: link.sh exposes exactly seven repo
symlinks under ~/.claude and neither daemon/ nor sessions/ is among them, so
`git ls-files` can never see them.

Left unfixed they would redden every sweep, which is the failure mode the
.env entry already argues against — a permanently red scan stops being read.

Scoped to the two exact filenames rather than the directories, and verified:
fake secrets planted beside them in the same dirs are still caught, and the
repo's own history stays clean (745 commits, no leaks).
2026-09-15 22:01:50 -04:00

104 lines
4.8 KiB
TOML

title = "claude-config gitleaks config"
# Backstop scanner (job7): pre-commit hook (lib/gitflow.sh emit-hook) and
# `make scan-secrets`. Extends gitleaks' default ruleset — never replaces it.
[extend]
useDefault = true
# 3 false-positive classes identified in job7 triage (.audit/job7/ALL-REDACTED.json),
# each verified empirically against the real flagged files before being added
# here (see .audit/job7-report.md). None of these are live secrets.
[[allowlists]]
description = "job7 triage — known false positives, not secrets"
# Content-based: git-game repo test fixtures (#5/#6 in the triage), confirmed
# synthetic by the repo owner — literal "test-secret-<digits>" values used in
# unit tests, flagged by the generic-api-key rule on entropy alone.
regexTarget = "match"
regexes = [
'''test-secret-[0-9-]+''',
]
# Path-based: third-party/vendored files outside our control, flagged by
# rules that don't apply to their content.
paths = [
# Official claude-plugins marketplace catalog — 40-char hex "sha" (git
# commit references, not credentials) trip the sourcegraph-access-token
# rule, which matches on bare hex length/entropy alone.
'''plugins/marketplaces/.*marketplace\.json$''',
# superpowers plugin test fixture — a base64-encoded WS protocol test
# nonce, not a credential, trips generic-api-key on entropy.
'''tests/brainstorm-server/ws-protocol\.test\.js$''',
# NOT a job7 false positive — this IS a real secret, by design: the
# canonical vault (BDR-026). `make scan-secrets` scans ~/.claude looking
# for stray COPIES of secrets outside this file; flagging the vault
# itself on every run is pure noise, not signal.
'''(^|/)\.env$''',
# seo-data OAuth token store — legitimate local secret (like ~/.claude/.env),
# 0600, outside git. Allowlisted so `make scan-secrets` doesn't flag the vault.
'''(^|/)\.claude/seo-data/tokens\.json$''',
]
# ── secrets-triage 2026-07-14 — 4 FP classes, each verified empirically
# (unredacted re-scan piped in-memory, values masked; see
# .gstack/security-reports/2026-07-14-secrets-triage.json). None are secrets.
# Transcripts and file-history are deliberately NOT path-allowlisted — that is
# where real leaks land (BDR-057).
# Bare 40-hex = git commit SHA (plugin-catalog pins, commit refs quoted in
# transcripts) tripping sourcegraph-access-token, which matches naked hex.
# Real sourcegraph tokens keep their sgp_ prefix → still detected.
[[allowlists]]
description = "bare 40-hex git commit SHAs (sourcegraph-access-token misfire)"
regexTarget = "secret"
regexes = ['''^[0-9a-f]{40}$''']
# Synthetic AWS key fabricated by lib/gitflow-test.sh:240 to exercise the
# pre-commit secret guard; test output lands in session transcripts.
[[allowlists]]
description = "gitflow-test synthetic AWS fixture (deliberately fake)"
regexTarget = "secret"
regexes = ['''AKIAGDR5XRBXYARW2I5N''']
# Public-by-design or expired URL credentials + documentation placeholders.
[[allowlists]]
description = "presigned-URL key ids, GitHub image JWTs, doc placeholders"
regexTarget = "line"
regexes = [
'''X-Amz-Credential=AKIA[0-9A-Z]{16}''',
'''private-user-images\.githubusercontent\.com/[^"]*\?jwt=''',
'''MAGIC_API_KEY=abc123''',
# magic MCP docs example — base64 of "the ..." ASCII sample text.
'''clientKey = 'dGhlIH[A-Za-z0-9+/=]*'''',
]
# Prose in transcripts near the word "tokens" — dictionary phrases flagged by
# generic-api-key on entropy alone (e.g. a design discussion of publish/reject
# token pairs). Exact literals only; transcripts stay fully scanned otherwise.
[[allowlists]]
description = "prose false positives in transcripts"
stopwords = ['''publish/reject''']
# Ephemeral machine-local IDE auth locks (rotate per IDE session, never leave
# the machine).
[[allowlists]]
description = "Claude Code IDE lock files"
paths = ['''(^|/)ide/[0-9]+\.lock$''']
# ── 2026-09-15 — Claude Code daemon/session runtime state, triaged on macOS.
# Same class as the IDE locks above: written by Claude Code itself, machine-
# local, ephemeral. Verified before allowlisting — roster.json's hits are the
# rendezvousSock/ptySock unix-socket paths and the sessionId UUID (paths, not
# credentials); sessions/*.key IS a real per-worker key, but 0600 and outside
# git. Neither directory is reachable from a commit: link.sh exposes exactly
# seven repo symlinks under ~/.claude (CLAUDE.md, settings.json, hooks, agents,
# skills, lib, templates) and these are not among them, so `git ls-files` can
# never see them. Scoped to the two exact filenames, NOT to the directories —
# a stray copy landing beside them stays detected.
[[allowlists]]
description = "Claude Code daemon roster + per-session keys (machine-local runtime state)"
paths = [
'''(^|/)\.claude/daemon/roster\.json$''',
'''(^|/)\.claude/sessions/[0-9]+\.[0-9a-f]{64}\.key$''',
]