| name | detect-hardcoded-secrets |
| description | Detect hardcoded secrets, API keys, passwords, and credentials in source code. Security audit for leaked secrets. Works across all languages. Use when user asks about security issues or secret detection. |
| allowed-tools | mcp__miller__fast_search, mcp__miller__get_symbols, Read, Grep |
Hardcoded Secrets Detection
Activation Announcement
IMPORTANT: When this skill activates, ALWAYS start your response with:
🔐 **Security Scan: Hardcoded Secrets**
Scanning codebase for exposed credentials and API keys...
This provides a visual indicator to the user that a security scan is running.
Why This Matters
Hardcoded secrets in source code:
- Get committed to git history (hard to remove)
- End up in logs, error messages, stack traces
- Get shared when code is shared
- Are a top cause of security breaches
Detection Strategy
Phase 1: High-Confidence Secret Patterns
Search for common secret variable names:
fast_search("password = api_key = secret =", method="text", limit=30)
fast_search("apiKey apiSecret accessToken", method="text", limit=30)
fast_search("connectionString credentials privateKey", method="text", limit=30)
fast_search("AWS_SECRET AZURE_KEY GITHUB_TOKEN", method="text", limit=30)
Phase 2: Assignment Pattern Detection
Look for string literals assigned to sensitive variables:
# Direct assignments
Grep pattern: '(password|secret|api_key|token|credential)\s*[=:]\s*["\x27][^"\x27]+["\x27]'
Grep pattern: '(Password|Secret|ApiKey|Token)\s*=\s*"[^"]+"'
# Common formats
fast_search("Bearer sk- pk- ghp_ xox", method="text", limit=30)
fast_search("-----BEGIN PRIVATE KEY-----", method="text", limit=10)
fast_search("-----BEGIN RSA PRIVATE KEY", method="text", limit=10)
Phase 3: Connection String Detection
fast_search("Server= User Id= Password=", method="text", limit=20)
fast_search("mongodb:// postgres:// mysql://", method="text", limit=20)
fast_search("redis:// amqp:// smtp://", method="text", limit=20)
fast_search("Data Source= Initial Catalog=", method="text", limit=20)
Phase 4: Cloud Provider Patterns
# AWS
fast_search("AKIA aws_access_key aws_secret", method="text", limit=20)
# Azure
fast_search("DefaultEndpointsProtocol AccountKey", method="text", limit=20)
# GCP
fast_search("type service_account private_key_id", method="text", limit=20)
# Generic
fast_search("client_secret tenant_id subscription", method="text", limit=20)
Phase 5: Verify Findings
For each suspicious result:
get_symbols(file_path="<file>", target="<function_or_class>", mode="full")
Determine if:
- It's a real secret (not a placeholder like "YOUR_KEY_HERE")
- It's in production code (not test fixtures)
- It looks like an actual credential format
Output Format
IMPORTANT: Always present findings in this structured format:
## Security Scan: Hardcoded Secrets
### ⚠️ WARNING
This scan found potential secrets. If any are real:
1. Rotate the credentials IMMEDIATELY
2. Use git-filter-branch or BFG to remove from history
3. Move secrets to environment variables or secret manager
### Summary
- Files scanned: X
- Potential secrets found: Y
- Severity: Critical: A, High: B, Medium: C
### Findings
#### 1. [CRITICAL] src/config/database.ts:23
**Type**: Database password
**Code**:
```typescript
const dbConfig = {
password: "Pr0d_P@ssw0rd_2024!" // ← EXPOSED
};
Risk: Database credentials exposed in source
Action: Move to environment variable DB_PASSWORD
2. [CRITICAL] src/services/stripe.cs:15
Type: API Key (Live) Code:
private const string ApiKey = "sk_live_EXAMPLE_FAKE_KEY_12345";
Risk: Live payment API key - financial exposure! Action: Use secret manager, rotate key immediately
3. [HIGH] config/settings.py:42
Type: Connection string with credentials Code:
MONGO_URI = "mongodb://admin:secretpass@prod.example.com:27017"
Risk: Full database access embedded Action: Split into components, use env vars
4. [MEDIUM] tests/fixtures/auth.json:8
Type: Test credentials Code:
{ "api_key": "test_key_12345" }
Risk: Lower (test data) but sets bad pattern Action: Use obviously fake values or env vars
Files to Exclude (False Positives)
.env.example- Template file with placeholdersdocs/setup.md- Documentation with fake examples
Recommendations
- Immediate: Rotate any real exposed credentials
- Short-term: Move secrets to environment variables
- Long-term: Implement secret manager (Vault, AWS Secrets Manager, etc.)
- Prevention: Add pre-commit hooks to detect secrets
## Secret Patterns Reference
### High-Confidence Patterns (Likely Real)
| Pattern | Example | Type |
|---------|---------|------|
| `sk_live_` | `sk_live_abc123...` | Stripe Live Key |
| `AKIA` | `AKIAIOSFODNN7EXAMPLE` | AWS Access Key |
| `ghp_` | `ghp_xxxxxxxxxxxx` | GitHub PAT |
| `xox[baprs]-` | `xoxb-123-456-abc` | Slack Token |
| `-----BEGIN.*PRIVATE KEY` | PEM format | Private Key |
| Base64 40+ chars after `=` | `apiKey=aGVsbG8gd29ybGQ...` | Encoded Secret |
### Medium-Confidence (Check Context)
| Pattern | Could Be |
|---------|----------|
| `password =` | Real password OR config key name |
| `secret =` | Real secret OR variable naming |
| `token =` | Auth token OR CSRF token name |
| Connection strings | Real creds OR template |
### Low-Confidence (Often False Positive)
| Pattern | Usually |
|---------|---------|
| `YOUR_KEY_HERE` | Placeholder |
| `xxx` or `***` | Redacted |
| `example.com` | Documentation |
| Test file paths | Test fixtures |
## Files to Skip
These locations often have intentional fake secrets:
- `*.example` files
- `*.sample` files
- `docs/` directory
- `test/fixtures/`
- `.env.template`
- `README.md`
But still flag them if they look like real credentials!
## Success Criteria
This skill succeeds when:
- Clear security warning at start
- Comprehensive search across secret types
- Findings categorized by severity and type
- False positives identified and explained
- Clear remediation steps provided
- Urgency communicated for critical findings