Secrets Scanner
What This Does
Scans codebases for hardcoded secrets — API keys, passwords, tokens, private keys, database connection strings, and other credentials that should never be committed to source code. Identifies exposed secrets, assesses the risk, and provides remediation steps including rotation procedures.
Instructions
Scan the codebase. Check systematically for:
High-confidence patterns:
- AWS access keys:
AKIA[A-Z0-9]{16}
- AWS secret keys: 40-character base64 strings near AWS context
- GitHub tokens:
ghp_[a-zA-Z0-9]{36}, gho_, ghs_, ghu_
- Slack tokens:
xoxb-, xoxp-, xoxs-
- Stripe keys:
sk_live_, sk_test_, pk_live_
- Private keys:
-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----
- JWT secrets: long random strings assigned to JWT_SECRET or similar
- Database URLs:
postgres://, mysql://, mongodb:// with credentials
- Generic API keys: variables named
*_API_KEY, *_SECRET, *_TOKEN, *_PASSWORD
Medium-confidence patterns:
- Base64-encoded strings > 20 characters in config files
- Hex strings > 32 characters in non-hash contexts
- URLs with embedded credentials (user:pass@host)
Check specific file types and locations:
Priority files:
- .env, .env.*, *.env (environment files)
- config.*, settings.*, *.config.* (configuration files)
- docker-compose.yml (often contains credentials)
- CI/CD configs (.github/workflows/, .gitlab-ci.yml, Jenkinsfile)
- Infrastructure as Code (terraform.tfvars, *.tf)
- Test fixtures and seed data
- README and documentation (example credentials that are real)
Check git history. Secrets removed from the current code may still be in commits:
# Search git history for secrets (use with caution on large repos)
git log -p --all -S "AKIA" -- . ":(exclude)node_modules"
git log -p --all -S "sk_live_" -- . ":(exclude)node_modules"
Verify findings. For each potential secret:
- Is it a real credential or a placeholder/example? (check for
example, placeholder, xxx, changeme)
- Is the file in
.gitignore? (still a risk if it was committed before)
- Is it a test credential? (lower severity but still flag it)
- Is it already in a secrets manager? (may be a copy that shouldn't be here)
Assess the impact. For confirmed secrets:
- What does this credential access? (database, payment system, cloud provider)
- Is the repository public or private?
- Has this been in git history? For how long?
- Who has access to this repository?
Remediate. For each confirmed secret:
- Rotate immediately: Generate a new credential and update the service
- Remove from code: Replace with environment variable reference
- Clean git history: If the repo is public, use
git filter-repo or BFG Repo-Cleaner
- Add to .gitignore: Prevent future commits of secret files
- Set up pre-commit hooks: Prevent future secrets from being committed
Set up prevention.
# Install gitleaks as a pre-commit hook
brew install gitleaks
gitleaks detect --source . --verbose
# Or use detect-secrets (Python)
pip install detect-secrets
detect-secrets scan > .secrets.baseline
Output Format
# Secrets Scan Report: {Repository}
**Date:** {YYYY-MM-DD}
**Files scanned:** {count}
**Secrets found:** {count}
## Critical Findings (Confirmed Secrets)
### {Secret Type}: {file path}:{line}
- **Type:** {API key / password / token / private key}
- **Service:** {what it accesses}
- **Risk:** {CRITICAL / HIGH}
- **In git history:** {Yes/No — how many commits}
- **Remediation:**
1. Rotate: {specific rotation steps for this service}
2. Remove: Replace with `process.env.{VAR_NAME}`
3. Add to `.env.example` with placeholder value
## Medium Confidence Findings
| File | Line | Pattern | Likely Type | Action |
|------|------|---------|-------------|--------|
| {file} | {line} | {matched pattern} | {type} | {verify/dismiss} |
## Prevention Setup
- [ ] `.gitignore` updated to exclude secret files
- [ ] Pre-commit hook installed (gitleaks/detect-secrets)
- [ ] CI pipeline includes secret scanning
- [ ] `.env.example` created with placeholder values
- [ ] Secrets migrated to {secrets manager}
## Rotation Checklist
- [ ] {Service 1}: Key rotated, old key revoked
- [ ] {Service 2}: Key rotated, old key revoked
Tips
- A secret in git history is as exposed as a secret in the current code — always check history
.env files should NEVER be committed, even to private repos — team members change, repos get transferred
- The most commonly leaked secrets: AWS keys, GitHub tokens, and database passwords
- If a secret was committed to a public repo, assume it has been scraped — rotate immediately
- Use 1Password, AWS Secrets Manager, or HashiCorp Vault for production secrets management
.env.example with placeholder values is the correct way to document required environment variables
- Pre-commit hooks are the best prevention — catch secrets before they enter git history
1---2name: secrets-scanner3description: Scan codebases for hardcoded secrets, API keys, tokens, passwords, and credentials with remediation guidance.4---56# Secrets Scanner78## What This Does910Scans codebases for hardcoded secrets — API keys, passwords, tokens, private keys, database connection strings, and other credentials that should never be committed to source code. Identifies exposed secrets, assesses the risk, and provides remediation steps including rotation procedures.1112## Instructions13141. **Scan the codebase.** Check systematically for:1516 **High-confidence patterns:**17 - AWS access keys: `AKIA[A-Z0-9]{16}`18 - AWS secret keys: 40-character base64 strings near AWS context19 - GitHub tokens: `ghp_[a-zA-Z0-9]{36}`, `gho_`, `ghs_`, `ghu_`20 - Slack tokens: `xoxb-`, `xoxp-`, `xoxs-`21 - Stripe keys: `sk_live_`, `sk_test_`, `pk_live_`22 - Private keys: `-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----`23 - JWT secrets: long random strings assigned to JWT_SECRET or similar24 - Database URLs: `postgres://`, `mysql://`, `mongodb://` with credentials25 - Generic API keys: variables named `*_API_KEY`, `*_SECRET`, `*_TOKEN`, `*_PASSWORD`2627 **Medium-confidence patterns:**28 - Base64-encoded strings > 20 characters in config files29 - Hex strings > 32 characters in non-hash contexts30 - URLs with embedded credentials (user:pass@host)31322. **Check specific file types and locations:**33 ```34 Priority files:35 - .env, .env.*, *.env (environment files)36 - config.*, settings.*, *.config.* (configuration files)37 - docker-compose.yml (often contains credentials)38 - CI/CD configs (.github/workflows/, .gitlab-ci.yml, Jenkinsfile)39 - Infrastructure as Code (terraform.tfvars, *.tf)40 - Test fixtures and seed data41 - README and documentation (example credentials that are real)42 ```43443. **Check git history.** Secrets removed from the current code may still be in commits:45 ```bash46 # Search git history for secrets (use with caution on large repos)47 git log -p --all -S "AKIA" -- . ":(exclude)node_modules"48 git log -p --all -S "sk_live_" -- . ":(exclude)node_modules"49 ```50514. **Verify findings.** For each potential secret:52 - Is it a real credential or a placeholder/example? (check for `example`, `placeholder`, `xxx`, `changeme`)53 - Is the file in `.gitignore`? (still a risk if it was committed before)54 - Is it a test credential? (lower severity but still flag it)55 - Is it already in a secrets manager? (may be a copy that shouldn't be here)56575. **Assess the impact.** For confirmed secrets:58 - What does this credential access? (database, payment system, cloud provider)59 - Is the repository public or private?60 - Has this been in git history? For how long?61 - Who has access to this repository?62636. **Remediate.** For each confirmed secret:64 - **Rotate immediately:** Generate a new credential and update the service65 - **Remove from code:** Replace with environment variable reference66 - **Clean git history:** If the repo is public, use `git filter-repo` or BFG Repo-Cleaner67 - **Add to .gitignore:** Prevent future commits of secret files68 - **Set up pre-commit hooks:** Prevent future secrets from being committed69707. **Set up prevention.**71 ```bash72 # Install gitleaks as a pre-commit hook73 brew install gitleaks74 gitleaks detect --source . --verbose7576 # Or use detect-secrets (Python)77 pip install detect-secrets78 detect-secrets scan > .secrets.baseline79 ```8081## Output Format8283```markdown84# Secrets Scan Report: {Repository}85**Date:** {YYYY-MM-DD}86**Files scanned:** {count}87**Secrets found:** {count}8889## Critical Findings (Confirmed Secrets)9091### {Secret Type}: {file path}:{line}92- **Type:** {API key / password / token / private key}93- **Service:** {what it accesses}94- **Risk:** {CRITICAL / HIGH}95- **In git history:** {Yes/No — how many commits}96- **Remediation:**97 1. Rotate: {specific rotation steps for this service}98 2. Remove: Replace with `process.env.{VAR_NAME}`99 3. Add to `.env.example` with placeholder value100101## Medium Confidence Findings102| File | Line | Pattern | Likely Type | Action |103|------|------|---------|-------------|--------|104| {file} | {line} | {matched pattern} | {type} | {verify/dismiss} |105106## Prevention Setup107- [ ] `.gitignore` updated to exclude secret files108- [ ] Pre-commit hook installed (gitleaks/detect-secrets)109- [ ] CI pipeline includes secret scanning110- [ ] `.env.example` created with placeholder values111- [ ] Secrets migrated to {secrets manager}112113## Rotation Checklist114- [ ] {Service 1}: Key rotated, old key revoked115- [ ] {Service 2}: Key rotated, old key revoked116```117118## Tips119120- A secret in git history is as exposed as a secret in the current code — always check history121- `.env` files should NEVER be committed, even to private repos — team members change, repos get transferred122- The most commonly leaked secrets: AWS keys, GitHub tokens, and database passwords123- If a secret was committed to a public repo, assume it has been scraped — rotate immediately124- Use 1Password, AWS Secrets Manager, or HashiCorp Vault for production secrets management125- `.env.example` with placeholder values is the correct way to document required environment variables126- Pre-commit hooks are the best prevention — catch secrets before they enter git history