Find credentials that should never be in version control — provider API keys, OAuth tokens, private keys, database URLs, and .env files — across a whole repo or a single diff. The skill greps for known key shapes, flags high-entropy strings, then triages each hit: real leak vs. example/test fixture vs. placeholder. For confirmed leaks it tells you the only safe remediation — rotate the credential and scrub history — because a secret that reached git is already compromised the moment it was pushed.
When to use this skill
- Before pushing a branch or opening a PR, to catch a credential that slipped into a commit.
- During review of a diff that touches config, CI, infrastructure, or
.env* files.
- After a suspected leak, to find every place a key appears across the working tree and history.
- When onboarding a repo and you want a baseline audit of what secrets may already be committed.
[!WARNING]
Deleting a secret from the latest commit does not remove it from history — it stays in every prior commit, every clone, and every fork. Any matched real key must be treated as compromised: rotate it first, then scrub history. Deletion alone is not remediation.
Instructions
- Define the scan target. Decide between the working tree (
git ls-files), a specific diff (git diff main...HEAD), or full history (git log -p / a dedicated history scanner). Diff scans are fast for PRs; full-tree scans catch already-committed leaks. Make the scope explicit in your report.
- Detect existing tooling and ignore rules — do not guess. Check for
.gitleaks.toml, .trufflehog*, detect-secrets baselines, or a pre-commit config. If a scanner is already configured, run it (gitleaks detect, trufflehog filesystem .) and honor its allowlist. Read .gitignore to see what should have been excluded but wasn't.
- Grep for known secret shapes. Search for provider-specific prefixes and structural patterns rather than generic words:
AKIA/ASIA (AWS), ghp_/gho_/github_pat_ (GitHub), sk-/sk-proj- (OpenAI), xox[baprs]- (Slack), AIza (Google), -----BEGIN .* PRIVATE KEY-----, JWTs (eyJ), and connection strings (postgres://, mongodb+srv:// with embedded credentials). Also glob for committed .env, .env.*, *.pem, *.p12, id_rsa, and *.keystore files.
- Flag high-entropy strings. For assignments like
token = "...", secret: ..., password=..., score the value's Shannon entropy; long base64/hex strings with high entropy near a secret-ish identifier are candidates even without a known prefix.
- Triage every hit. This is the core of the skill — separate true positives from noise: a value in
*.example, *.sample, fixtures/, test/, or a docs snippet, or an obvious placeholder (xxx, your-key-here, changeme, dummy, all-zeros) is a false positive. A live-looking value in real config, source, or CI is a true positive. When unsure, mark it review rather than dismissing it.
- Verify the finding set. Re-run your matches with
git grep -n to attach exact file:line locations, and confirm each true positive is reachable in a tracked file (not just an ignored local file). For history claims, verify with git log -p -S '<fragment>'.
- Report and remediate. Output a triaged findings table (file, line, type, verdict). For every true positive, give the two-step fix in order: (1) rotate the credential at the provider and invalidate the old one; (2) scrub history with
git filter-repo --replace-text or BFG, then force-push and have collaborators re-clone. Flag any review items needing human judgment and recommend adding a pre-commit secret scanner to prevent recurrence.
[!NOTE]
Rotation comes before scrubbing. Scrubbing hides the secret going forward but cannot un-leak what was already pushed; only rotation makes the exposed value worthless.
Examples
Triaged output for a branch diff:
$ git diff main...HEAD | secret-scanner
Findings (4 matches, scope: diff main...HEAD)
| File | Line | Type | Verdict |
|-------------------------------|------|---------------------|----------------|
| src/config/aws.ts | 12 | AWS access key (AKIA) | TRUE POSITIVE |
| .env | 1 | committed .env file | TRUE POSITIVE |
| test/fixtures/stripe.json | 8 | Stripe TEST key (sk_test_) | false positive |
| README.md | 44 | placeholder API key | false positive |
2 true positives. ACTION REQUIRED.
src/config/aws.ts:12 AKIAIOSFODNN7EXAMPLE...
-> ROTATE: deactivate this access key in IAM and issue a new one.
-> SCRUB: git filter-repo --replace-text <(echo 'AKIAIOSFODNN7EXAMPLE==>REMOVED')
then force-push; ask collaborators to re-clone.
.env:1 contains DATABASE_URL with embedded password
-> ROTATE: change the database password now.
-> SCRUB: git rm --cached .env && add `.env` to .gitignore, then filter-repo
to purge it from history.
Recommendation: add gitleaks as a pre-commit hook to block future leaks.
[!WARNING]
The sk_test_ Stripe key and the README placeholder are intentionally inert — flagging them as incidents wastes responder time and erodes trust in the scanner. Triage before you alarm.
1---2name: secret-scanner3description: Scan a repo or a diff for committed secrets — API keys, tokens, private keys, .env files, and high-entropy strings — then triage real leaks from fixtures. Use before pushing, in review, or when a credential may have leaked.4---56Find credentials that should never be in version control — provider API keys, OAuth tokens, private keys, database URLs, and `.env` files — across a whole repo or a single diff. The skill greps for known key shapes, flags high-entropy strings, then triages each hit: real leak vs. example/test fixture vs. placeholder. For confirmed leaks it tells you the only safe remediation — **rotate the credential and scrub history** — because a secret that reached `git` is already compromised the moment it was pushed.78## When to use this skill910- Before pushing a branch or opening a PR, to catch a credential that slipped into a commit.11- During review of a diff that touches config, CI, infrastructure, or `.env*` files.12- After a suspected leak, to find every place a key appears across the working tree and history.13- When onboarding a repo and you want a baseline audit of what secrets may already be committed.1415> [!WARNING]16> Deleting a secret from the latest commit does **not** remove it from history — it stays in every prior commit, every clone, and every fork. Any matched real key must be treated as compromised: **rotate it first**, then scrub history. Deletion alone is not remediation.1718## Instructions19201. **Define the scan target.** Decide between the working tree (`git ls-files`), a specific diff (`git diff main...HEAD`), or full history (`git log -p` / a dedicated history scanner). Diff scans are fast for PRs; full-tree scans catch already-committed leaks. Make the scope explicit in your report.212. **Detect existing tooling and ignore rules — do not guess.** Check for `.gitleaks.toml`, `.trufflehog*`, `detect-secrets` baselines, or a `pre-commit` config. If a scanner is already configured, run it (`gitleaks detect`, `trufflehog filesystem .`) and honor its allowlist. Read `.gitignore` to see what *should* have been excluded but wasn't.223. **Grep for known secret shapes.** Search for provider-specific prefixes and structural patterns rather than generic words: `AKIA`/`ASIA` (AWS), `ghp_`/`gho_`/`github_pat_` (GitHub), `sk-`/`sk-proj-` (OpenAI), `xox[baprs]-` (Slack), `AIza` (Google), `-----BEGIN .* PRIVATE KEY-----`, JWTs (`eyJ`), and connection strings (`postgres://`, `mongodb+srv://` with embedded credentials). Also glob for committed `.env`, `.env.*`, `*.pem`, `*.p12`, `id_rsa`, and `*.keystore` files.234. **Flag high-entropy strings.** For assignments like `token = "..."`, `secret: ...`, `password=...`, score the value's Shannon entropy; long base64/hex strings with high entropy near a secret-ish identifier are candidates even without a known prefix.245. **Triage every hit.** This is the core of the skill — separate true positives from noise: a value in `*.example`, `*.sample`, `fixtures/`, `test/`, or a docs snippet, or an obvious placeholder (`xxx`, `your-key-here`, `changeme`, `dummy`, all-zeros) is a **false positive**. A live-looking value in real config, source, or CI is a **true positive**. When unsure, mark it `review` rather than dismissing it.256. **Verify the finding set.** Re-run your matches with `git grep -n` to attach exact `file:line` locations, and confirm each true positive is reachable in a tracked file (not just an ignored local file). For history claims, verify with `git log -p -S '<fragment>'`.267. **Report and remediate.** Output a triaged findings table (file, line, type, verdict). For every true positive, give the two-step fix in order: **(1) rotate** the credential at the provider and invalidate the old one; **(2) scrub history** with `git filter-repo --replace-text` or BFG, then force-push and have collaborators re-clone. Flag any `review` items needing human judgment and recommend adding a pre-commit secret scanner to prevent recurrence.2728> [!NOTE]29> Rotation comes before scrubbing. Scrubbing hides the secret going forward but cannot un-leak what was already pushed; only rotation makes the exposed value worthless.3031## Examples3233Triaged output for a branch diff:3435```text36$ git diff main...HEAD | secret-scanner3738Findings (4 matches, scope: diff main...HEAD)3940| File | Line | Type | Verdict |41|-------------------------------|------|---------------------|----------------|42| src/config/aws.ts | 12 | AWS access key (AKIA) | TRUE POSITIVE |43| .env | 1 | committed .env file | TRUE POSITIVE |44| test/fixtures/stripe.json | 8 | Stripe TEST key (sk_test_) | false positive |45| README.md | 44 | placeholder API key | false positive |46472 true positives. ACTION REQUIRED.4849src/config/aws.ts:12 AKIAIOSFODNN7EXAMPLE...50 -> ROTATE: deactivate this access key in IAM and issue a new one.51 -> SCRUB: git filter-repo --replace-text <(echo 'AKIAIOSFODNN7EXAMPLE==>REMOVED')52 then force-push; ask collaborators to re-clone.5354.env:1 contains DATABASE_URL with embedded password55 -> ROTATE: change the database password now.56 -> SCRUB: git rm --cached .env && add `.env` to .gitignore, then filter-repo57 to purge it from history.5859Recommendation: add gitleaks as a pre-commit hook to block future leaks.60```6162> [!WARNING]63> The `sk_test_` Stripe key and the README placeholder are intentionally inert — flagging them as incidents wastes responder time and erodes trust in the scanner. Triage before you alarm.