From memstack
Scans codebases for hardcoded secrets, API keys (Stripe, Supabase, AWS, GitHub, Slack), bearer tokens, passwords, private keys, and base64 secrets using grep regex patterns on JS/TS/JSON/YAML files.
npx claudepluginhub cwinvestments/memstack --plugin memstackThis skill uses the workspace's default tool permissions.
*Scan a codebase for hardcoded secrets, leaked API keys, and credential exposure across files and git history.*
Scans code, git history, and configs for secrets like API keys, cloud credentials, private keys, and DB strings using regex, entropy, and context. Assesses severity and generates remediation reports.
Detects hardcoded secrets like API keys, tokens, and credentials in git repos using Gitleaks regex and entropy analysis. Guides repo scans, pre-commit hooks, CI/CD integration, audits.
Provides multi-layer secret protection: AI write rules, Gitleaks pre-commit scanning, repo pattern detection, token lifecycle management, deploy/runtime guards. Use before git push/deploy or new projects.
Share bugs, ideas, or general feedback.
Scan a codebase for hardcoded secrets, leaked API keys, and credential exposure across files and git history.
When this skill activates, output:
π Secrets Scanner β Scanning for Exposed Credentials...
Then execute the protocol below.
| Context | Status |
|---|---|
| User asks to scan for secrets/keys | ACTIVE β full scan |
| User mentions credential exposure | ACTIVE β full scan |
| User asks about .env security | ACTIVE β targeted .env audit |
| Pre-deployment security review | ACTIVE β full scan |
| User is creating .env files | DORMANT β let them work |
Search all tracked files for strings matching known secret patterns:
API Key Patterns:
# Stripe
grep -rn "sk_live_[a-zA-Z0-9]\{20,\}\|sk_test_[a-zA-Z0-9]\{20,\}\|pk_live_[a-zA-Z0-9]\{20,\}" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.json" --include="*.md" --include="*.yaml" --include="*.yml" .
# Supabase
grep -rn "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\." --include="*.ts" --include="*.tsx" --include="*.js" .
# AWS
grep -rn "AKIA[0-9A-Z]\{16\}" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.json" --include="*.env*" .
# GitHub tokens
grep -rn "ghp_[a-zA-Z0-9]\{36\}\|gho_[a-zA-Z0-9]\{36\}\|github_pat_[a-zA-Z0-9_]\{30,\}" .
# Slack tokens
grep -rn "xoxb-[0-9]\{10,\}\|xoxp-[0-9]\{10,\}\|xoxs-[0-9]\{10,\}" .
# Generic high-entropy strings assigned to obvious secret variables
grep -rn "api_key\s*=\s*['\"][a-zA-Z0-9]\{20,\}['\"]\|apiKey\s*[:=]\s*['\"][a-zA-Z0-9]\{20,\}['\"]" .
Authentication Patterns:
# Bearer tokens hardcoded
grep -rn "Bearer [a-zA-Z0-9_\-\.]\{20,\}" --include="*.ts" --include="*.tsx" --include="*.js" .
# Passwords in code
grep -rn "password\s*[:=]\s*['\"][^'\"]\{4,\}['\"]\|PASSWORD\s*=\s*['\"][^'\"]\{4,\}['\"]" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.json" .
Private Keys:
# RSA/EC/DSA/OpenSSH private keys
grep -rn "BEGIN.*PRIVATE KEY\|BEGIN RSA PRIVATE\|BEGIN EC PRIVATE\|BEGIN DSA PRIVATE\|BEGIN OPENSSH PRIVATE" \
--include="*.ts" --include="*.tsx" --include="*.js" --include="*.json" --include="*.pem" --include="*.key" --include="*.yaml" --include="*.yml" --include="*.md" .
Flag as CRITICAL if found in any tracked file. Private keys should never be committed β use environment variables or secret managers.
Base64-Encoded Secrets:
# Look for base64-encoded strings assigned to secret-like variables
# These are often used to obfuscate secrets in source code
grep -rn "\(secret\|key\|token\|password\|credential\).*['\"][ ]*[A-Za-z0-9+/]\{40,\}=*['\"]" \
--include="*.ts" --include="*.tsx" --include="*.js" --include="*.json" .
# Check for Buffer.from(... 'base64') with hardcoded strings
grep -rn "Buffer\.from(['\"][A-Za-z0-9+/]\{20,\}=*['\"].*base64\|atob(['\"][A-Za-z0-9+/]\{20,\}" \
--include="*.ts" --include="*.tsx" --include="*.js" .
Flag as WARNING if a base64 string is assigned to a variable with secret, key, token, or password in its name. Developers sometimes base64-encode secrets thinking it hides them β it doesn't.
Connection Strings:
# Database URLs with credentials
grep -rn "postgres://[^:]\+:[^@]\+@\|mysql://[^:]\+:[^@]\+@\|mongodb://[^:]\+:[^@]\+@\|redis://:[^@]\+@" .
# Supabase/Firebase URLs with keys inline
grep -rn "supabase\.co.*service_role\|firebaseio\.com.*AIza" --include="*.ts" --include="*.tsx" --include="*.js" .
Exclude false positives:
node_modules/, .git/, dist/, .next/sk_test_fake123)process.env.STRIPE_SECRET_KEY is safe β the variable itself, not a value)Check if .env files are gitignored:
# Are .env files in .gitignore?
grep -n "\.env" .gitignore
# Are any .env files currently tracked?
git ls-files | grep -i "\.env"
# Were .env files ever committed?
git log --all --diff-filter=A --name-only --pretty=format: | grep -i "\.env" | sort -u
Flag as CRITICAL if:
.env or .env.local is currently tracked by git.env was previously committed (secrets in git history even if now removed).gitignore does not contain .env patternsCheck .env.example exists:
Secrets often leak into files developers don't think about:
# Check CLAUDE.md, README, docs
grep -rn "sk_\|pk_\|AKIA\|ghp_\|password\s*[:=]" *.md docs/ CLAUDE.md README.md 2>/dev/null
# Check config files
grep -rn "sk_\|pk_\|AKIA\|secret\|password\|token" \
--include="*.json" --include="*.yaml" --include="*.yml" --include="*.toml" \
--exclude-dir=node_modules .
# Check CI/CD config files
grep -rn "sk_\|pk_\|AKIA\|password\|token" \
.github/workflows/*.yml .gitlab-ci.yml Dockerfile docker-compose*.yml 2>/dev/null
Flag as CRITICAL if real secrets found in any committed documentation or config.
Secrets can leak into platform-specific deployment configurations:
# Netlify config
grep -rn "password\|secret\|token\|api_key\|AKIA\|sk_\|pk_" \
netlify.toml netlify.yml 2>/dev/null
# Vercel config
grep -rn "password\|secret\|token\|api_key\|AKIA\|sk_\|pk_" \
vercel.json .vercel/project.json 2>/dev/null
# Railway config
grep -rn "password\|secret\|token\|api_key" \
railway.json railway.toml 2>/dev/null
# Render config
grep -rn "password\|secret\|token\|api_key" \
render.yaml 2>/dev/null
# Fly.io config
grep -rn "password\|secret\|token\|api_key" \
fly.toml 2>/dev/null
Flag as CRITICAL if:
netlify.toml [build.environment] section contains secret values (these are committed to git β use Netlify UI environment variables instead)vercel.json contains environment variable values (use vercel env CLI or Dashboard instead)Flag as WARNING if:
Verify env vars are validated at application startup:
Search for unvalidated env var usage:
# Direct process.env usage without validation
grep -rn "process\.env\.\(.*SECRET\|.*KEY\|.*TOKEN\|.*PASSWORD\|.*DATABASE_URL\)" \
--include="*.ts" --include="*.tsx" --include="*.js" .
Flag as WARNING if:
process.env.SECRET_NAME used directly without checking if defined@t3-oss/env-nextjs, envalid, zod env schema)Correct pattern:
// Good β validated at startup
import { z } from 'zod';
const env = z.object({
DATABASE_URL: z.string().url(),
STRIPE_SECRET_KEY: z.string().startsWith('sk_'),
}).parse(process.env);
Server-only secrets must never reach the browser:
Search for secrets in client code:
# In React/Next.js, only NEXT_PUBLIC_ vars are safe for client
grep -rn "process\.env\." --include="*.tsx" --include="*.jsx" \
src/app/ src/components/ src/pages/ app/ components/ pages/ 2>/dev/null \
| grep -v "NEXT_PUBLIC_"
Flag as CRITICAL if:
SUPABASE_SERVICE_ROLE_KEY referenced in client componentsSTRIPE_SECRET_KEY (not STRIPE_PUBLISHABLE_KEY) in client codeDATABASE_URL in client codeNEXT_PUBLIC_ env var in files under app/, components/, pages/ (client-rendered paths)Flag as WARNING if:
Previously committed secrets remain in git history even after removal:
# Search git history for known secret patterns
git log -p --all -S "sk_live" --oneline -- "*.ts" "*.tsx" "*.js" "*.json" "*.env" 2>/dev/null | head -20
git log -p --all -S "AKIA" --oneline 2>/dev/null | head -20
git log -p --all -S "ghp_" --oneline 2>/dev/null | head -20
git log -p --all -S "password" --oneline -- "*.env" "*.env.*" 2>/dev/null | head -20
Flag as CRITICAL if:
Remediation for exposed history:
git filter-branch or BFG Repo-Cleaner to purge from history# Secrets in Dockerfiles
grep -rn "ENV.*SECRET\|ENV.*KEY\|ENV.*PASSWORD\|ENV.*TOKEN\|ARG.*SECRET" \
Dockerfile* docker-compose*.yml 2>/dev/null
# Secrets passed as build args
grep -rn "build-arg.*secret\|build-arg.*key\|build-arg.*password" \
Dockerfile* .github/workflows/*.yml 2>/dev/null
Flag as CRITICAL if:
Flag as WARNING if:
π Secrets Scanner Report
Project: <project-name>
Files scanned: <count>
Git history checked: <yes/no>
## Findings
| # | File | Line | Type | Pattern | Risk | Status |
|---|------|------|------|---------|------|--------|
| 1 | src/lib/stripe.ts | 14 | Stripe Secret Key | sk_live_... | π΄ CRIT | Hardcoded |
| 2 | .env | β | Environment File | .env tracked | π΄ CRIT | In git |
| 3 | docker-compose.yml | 23 | Database Password | password= | β οΈ WARN | Inline |
| 4 | src/app/page.tsx | 8 | Server Env in Client | DATABASE_URL | π΄ CRIT | Client-exposed |
| 5 | README.md | 45 | API Key Example | sk_test_... | βΉοΈ INFO | Test key |
## Critical Issues
1. **Stripe secret key hardcoded** in `src/lib/stripe.ts:14`
β Fix: Move to `.env.local` as `STRIPE_SECRET_KEY`, reference via `process.env.STRIPE_SECRET_KEY`
β Then: Rotate the key in Stripe Dashboard immediately β it's been committed
2. **.env file tracked in git**
β Fix: `git rm --cached .env && echo ".env" >> .gitignore && git commit`
β Then: Rotate ALL credentials that were in the .env file
3. **DATABASE_URL in client component**
β Fix: Move database access to server-side API route or Server Component
## Git History
- β οΈ Found `sk_live_` pattern in commit `a1b2c3d` (2024-03-15)
β Credential was removed but remains in history
β Fix: Rotate the key, then clean history with BFG Repo-Cleaner
## Environment File Audit
- .gitignore: β
Contains .env patterns
- .env tracked: π΄ Yes β remove immediately
- .env.example: β οΈ Missing β create with placeholder values
- Env validation: β οΈ No startup validation found
## Summary
- π΄ Critical: <count>
- β οΈ Warning: <count>
- βΉοΈ Info: <count>
- Files with secrets: <count>
- Git history exposures: <count>
If no .env.example exists, offer to create one:
# Extract all env var names from the codebase
grep -roh "process\.env\.[A-Z_]\+" --include="*.ts" --include="*.tsx" --include="*.js" . \
| sort -u \
| sed 's/process\.env\.//' \
> /tmp/env_vars.txt
Generate .env.example with all discovered variables and placeholder values:
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# Stripe
STRIPE_SECRET_KEY=sk_test_your-key
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your-key
STRIPE_WEBHOOK_SECRET=whsec_your-secret
Before rotating any exposed credential, verify:
Rotation priority:
| Secret Type | Urgency | Reason |
|---|---|---|
| Payment keys (Stripe, Square) | Immediate | Financial fraud risk |
| Database credentials | Immediate | Full data access |
| Auth secrets (JWT, session) | Immediate | Session hijacking |
| API keys (SendGrid, OpenAI) | High | Abuse/cost risk |
| Monitoring tokens (Sentry, Datadog) | Medium | Limited blast radius |
| Internal service keys | Medium | Depends on what they access |
Always conclude with:
.env patterns to .gitignore before any new commits.env.example with placeholder values for onboarding@t3-oss/env-nextjs or Zod schema) to catch missing vars at startupNEXT_PUBLIC_ prefix only for values safe to expose to browsersBFG Repo-Cleaner)| Level | Meaning | Action |
|---|---|---|
| π΄ CRITICAL | Live secret exposed in code or git history | Rotate immediately, then fix |
| β οΈ WARNING | Weak secret hygiene or missing safeguards | Fix before next deploy |
| βΉοΈ INFO | Test/example keys or minor hygiene issue | Review and confirm acceptable |
| β OK | Properly managed | No action needed |
| Pattern | Service | Example |
|---|---|---|
sk_live_* / sk_test_* | Stripe Secret | sk_live_51J... |
pk_live_* / pk_test_* | Stripe Publishable | pk_live_51J... |
whsec_* | Stripe Webhook | whsec_abc... |
AKIA* (20 chars) | AWS Access Key | AKIAIOSFODNN7EXAMPLE |
ghp_* (36 chars) | GitHub PAT | ghp_xxxxxxxxxxxx |
gho_* | GitHub OAuth | gho_xxxxxxxxxxxx |
github_pat_* | GitHub Fine-grained PAT | github_pat_11A... |
xoxb-* | Slack Bot Token | xoxb-123-456-abc |
xoxp-* | Slack User Token | xoxp-123-456-abc |
SG.* (69 chars) | SendGrid | SG.xxxxxxxxxx |
eyJhbGci* | JWT (Supabase/Auth) | eyJhbGciOiJIUzI1... |
sk-* (48+ chars) | OpenAI API Key | sk-abc123... |
Bearer * | Auth Header | Bearer eyJ... |
-----BEGIN RSA PRIVATE KEY----- | RSA Private Key | PEM block |
-----BEGIN EC PRIVATE KEY----- | EC Private Key | PEM block |
-----BEGIN OPENSSH PRIVATE KEY----- | SSH Private Key | OpenSSH format |
| Base64 in secret var | Obfuscated secret | c2VjcmV0X2tleQ== |
The MemStack Pro hook system provides automatic, production-grade secrets detection before every commit and push β no manual invocation required.
Pre-Commit Hook β Scans all staged files before any git commit. Detects 700+ credential formats across every major cloud provider, SaaS API, private key format, and authentication token type. Blocks the commit if secrets are found, with redacted output showing what was detected and where.
Pre-Push Hook β Full working-tree scan before any git push. Catches secrets that may have been committed across multiple commits since the last push. Also detects .env files in unpushed commits.
Coverage includes:
Fallback behavior: If the production scanner is not installed, hooks silently fall back to the built-in 5-keyword regex scan (Step 1 patterns). Scanning is never skipped β only the depth of detection changes.
This manual skill remains available for deep audits β git history analysis, client-side exposure checks, env validation, Docker inspection, and remediation planning that go beyond what automated hooks cover.
Pro: Secrets scanning hooks run automatically before every commit and push, covering 700+ credential formats across every major cloud provider and API service. Free version requires manual scanning only.