SC: Hardcoded Secrets & Credentials
Purpose
Detects hardcoded secrets, API keys, tokens, passwords, private keys, and credentials embedded in source code, configuration files, and environment files committed to version control. Uses pattern matching for known key formats, entropy analysis for unknown formats, and context analysis to distinguish test keys from production secrets.
Activation
Called by sc-orchestrator during Phase 2. Always runs regardless of detected languages.
Phase 1: Discovery
File Patterns to Search
**/*.ts, **/*.js, **/*.py, **/*.go, **/*.php, **/*.java, **/*.cs,
**/*.rb, **/*.yaml, **/*.yml, **/*.json, **/*.xml, **/*.toml,
**/*.env, **/*.env.*, **/*.cfg, **/*.conf, **/*.ini, **/*.properties,
**/*.config, **/config/*, **/settings/*, **/.env*, **/docker-compose*,
**/*.sh, **/*.bash, **/Dockerfile*, **/.github/workflows/*
Known API Key Patterns
| Service |
Pattern |
Example Prefix |
| AWS Access Key |
AKIA[0-9A-Z]{16} |
AKIA... |
| AWS Secret Key |
40-char base64 after aws_secret_access_key |
|
| GitHub Token |
ghp_[A-Za-z0-9]{36} |
ghp_... |
| GitHub App Token |
ghs_[A-Za-z0-9]{36} |
ghs_... |
| GitLab Token |
glpat-[A-Za-z0-9\-]{20} |
glpat-... |
| Stripe Live Key |
sk_live_[A-Za-z0-9]{24,} |
sk_live_... |
| Stripe Publishable |
pk_live_[A-Za-z0-9]{24,} |
pk_live_... |
| Twilio |
SK[0-9a-fA-F]{32} |
SK... |
| SendGrid |
SG\.[A-Za-z0-9\-_]{22}\.[A-Za-z0-9\-_]{43} |
SG.... |
| Slack Token |
xox[baprs]-[A-Za-z0-9\-]{10,} |
xoxb-... |
| Google API Key |
AIza[A-Za-z0-9\-_]{35} |
AIza... |
| Firebase Key |
AAAA[A-Za-z0-9_-]{7}:[A-Za-z0-9_-]{140} |
|
| Heroku API Key |
[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-...-[0-9a-fA-F]{12} |
UUID format |
| npm Token |
npm_[A-Za-z0-9]{36} |
npm_... |
| PyPI Token |
pypi-[A-Za-z0-9\-_]{16,} |
pypi-... |
Private Key Detection
"-----BEGIN RSA PRIVATE KEY-----"
"-----BEGIN EC PRIVATE KEY-----"
"-----BEGIN OPENSSH PRIVATE KEY-----"
"-----BEGIN PGP PRIVATE KEY BLOCK-----"
"-----BEGIN DSA PRIVATE KEY-----"
"-----BEGIN PRIVATE KEY-----"
Generic Secret Patterns
# Assignment patterns
"password\s*[=:]\s*[\"'][^\"']{8,}"
"secret\s*[=:]\s*[\"'][^\"']{8,}"
"api_key\s*[=:]\s*[\"'][^\"']{8,}"
"token\s*[=:]\s*[\"'][^\"']{8,}"
"private_key\s*[=:]\s*[\"'][^\"']{8,}"
"auth.*[=:]\s*[\"'][^\"']{8,}"
"credential.*[=:]\s*[\"'][^\"']{8,}"
# Connection strings with embedded passwords
"mongodb://.*:.*@"
"postgres://.*:.*@"
"mysql://.*:.*@"
"redis://.*:.*@"
"amqp://.*:.*@"
High-Entropy String Detection
Flag strings with Shannon entropy > 4.5 in security-sensitive variable assignments.
Phase 2: Verification
Test vs Production Key Distinction
- Does the key match a known test/example prefix? (e.g.,
sk_test_, pk_test_, AKIAIOSFODNN7EXAMPLE)
- Is the file in a test directory?
- Is the value
"changeme", "placeholder", "xxx", "your-key-here"?
- Is the value loaded from an environment variable at runtime? (
os.getenv(), process.env)
- Is the
.env file in .gitignore?
Context Analysis
# FALSE POSITIVE: Environment variable read (not hardcoded)
API_KEY = os.environ.get('API_KEY')
# TRUE POSITIVE: Hardcoded secret
API_KEY = "sk_live_EXAMPLE_KEY_REPLACE_ME"
# FALSE POSITIVE: Test key
STRIPE_KEY = "sk_test_EXAMPLE_KEY"
# TRUE POSITIVE: Production key in code
STRIPE_KEY = "sk_live_EXAMPLE_PROD_KEY"
Severity Classification
- Critical: Production API keys (AWS, Stripe live, database passwords), private keys, JWT signing secrets
- High: Service tokens (GitHub, GitLab, Slack, SendGrid) that grant significant access
- Medium: API keys with limited scope, internal service credentials, publishable keys misidentified as secret
- Low: Test/sandbox keys, example/placeholder values, keys in documentation
Output Format
Finding: SECRET-{NNN}
- Title: Hardcoded {key type} in {file}
- Severity: Critical | High | Medium | Low
- Confidence: 0-100
- File: file/path:line
- Vulnerability Type: CWE-798 (Hardcoded Credentials) | CWE-321 (Hard-coded Cryptographic Key)
- Description: {Service} {key type} found hardcoded in source code.
- Impact: Unauthorized access to {service}, data breach, financial loss, account compromise.
- Remediation: Move secret to environment variable or secrets manager. Rotate the exposed key immediately.
- References: https://cwe.mitre.org/data/definitions/798.html
Common False Positives
- Environment variable reads —
os.getenv("KEY"), process.env.KEY are runtime reads, not hardcoded
- Test/sandbox keys —
sk_test_, pk_test_, keys containing "test", "example", "demo"
- Placeholder values —
"changeme", "your-api-key", "xxx", "TODO"
- Public keys — SSH public keys, JWT public keys, certificate public keys are not secrets
- Hash outputs — bcrypt hashes, SHA hashes in migration files are not secrets
- Base64-encoded non-secrets — base64 strings that are UI assets, not credentials
- Configuration templates —
.env.example files with placeholder values
1---2name: sc-secrets3description: Hardcoded secrets, API keys, tokens, credentials, and private key detection in source code4license: MIT5---67# SC: Hardcoded Secrets & Credentials89## Purpose1011Detects hardcoded secrets, API keys, tokens, passwords, private keys, and credentials embedded in source code, configuration files, and environment files committed to version control. Uses pattern matching for known key formats, entropy analysis for unknown formats, and context analysis to distinguish test keys from production secrets.1213## Activation1415Called by sc-orchestrator during Phase 2. Always runs regardless of detected languages.1617## Phase 1: Discovery1819### File Patterns to Search20```21**/*.ts, **/*.js, **/*.py, **/*.go, **/*.php, **/*.java, **/*.cs,22**/*.rb, **/*.yaml, **/*.yml, **/*.json, **/*.xml, **/*.toml,23**/*.env, **/*.env.*, **/*.cfg, **/*.conf, **/*.ini, **/*.properties,24**/*.config, **/config/*, **/settings/*, **/.env*, **/docker-compose*,25**/*.sh, **/*.bash, **/Dockerfile*, **/.github/workflows/*26```2728### Known API Key Patterns2930| Service | Pattern | Example Prefix |31|---------|---------|----------------|32| AWS Access Key | `AKIA[0-9A-Z]{16}` | `AKIA...` |33| AWS Secret Key | 40-char base64 after `aws_secret_access_key` | |34| GitHub Token | `ghp_[A-Za-z0-9]{36}` | `ghp_...` |35| GitHub App Token | `ghs_[A-Za-z0-9]{36}` | `ghs_...` |36| GitLab Token | `glpat-[A-Za-z0-9\-]{20}` | `glpat-...` |37| Stripe Live Key | `sk_live_[A-Za-z0-9]{24,}` | `sk_live_...` |38| Stripe Publishable | `pk_live_[A-Za-z0-9]{24,}` | `pk_live_...` |39| Twilio | `SK[0-9a-fA-F]{32}` | `SK...` |40| SendGrid | `SG\.[A-Za-z0-9\-_]{22}\.[A-Za-z0-9\-_]{43}` | `SG....` |41| Slack Token | `xox[baprs]-[A-Za-z0-9\-]{10,}` | `xoxb-...` |42| Google API Key | `AIza[A-Za-z0-9\-_]{35}` | `AIza...` |43| Firebase Key | `AAAA[A-Za-z0-9_-]{7}:[A-Za-z0-9_-]{140}` | |44| Heroku API Key | `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-...-[0-9a-fA-F]{12}` | UUID format |45| npm Token | `npm_[A-Za-z0-9]{36}` | `npm_...` |46| PyPI Token | `pypi-[A-Za-z0-9\-_]{16,}` | `pypi-...` |4748### Private Key Detection49```50"-----BEGIN RSA PRIVATE KEY-----"51"-----BEGIN EC PRIVATE KEY-----"52"-----BEGIN OPENSSH PRIVATE KEY-----"53"-----BEGIN PGP PRIVATE KEY BLOCK-----"54"-----BEGIN DSA PRIVATE KEY-----"55"-----BEGIN PRIVATE KEY-----"56```5758### Generic Secret Patterns59```60# Assignment patterns61"password\s*[=:]\s*[\"'][^\"']{8,}"62"secret\s*[=:]\s*[\"'][^\"']{8,}"63"api_key\s*[=:]\s*[\"'][^\"']{8,}"64"token\s*[=:]\s*[\"'][^\"']{8,}"65"private_key\s*[=:]\s*[\"'][^\"']{8,}"66"auth.*[=:]\s*[\"'][^\"']{8,}"67"credential.*[=:]\s*[\"'][^\"']{8,}"6869# Connection strings with embedded passwords70"mongodb://.*:.*@"71"postgres://.*:.*@"72"mysql://.*:.*@"73"redis://.*:.*@"74"amqp://.*:.*@"75```7677### High-Entropy String Detection78Flag strings with Shannon entropy > 4.5 in security-sensitive variable assignments.7980## Phase 2: Verification8182### Test vs Production Key Distinction831. Does the key match a known test/example prefix? (e.g., `sk_test_`, `pk_test_`, `AKIAIOSFODNN7EXAMPLE`)842. Is the file in a test directory?853. Is the value `"changeme"`, `"placeholder"`, `"xxx"`, `"your-key-here"`?864. Is the value loaded from an environment variable at runtime? (`os.getenv()`, `process.env`)875. Is the `.env` file in `.gitignore`?8889### Context Analysis90```python91# FALSE POSITIVE: Environment variable read (not hardcoded)92API_KEY = os.environ.get('API_KEY')9394# TRUE POSITIVE: Hardcoded secret95API_KEY = "sk_live_EXAMPLE_KEY_REPLACE_ME"9697# FALSE POSITIVE: Test key98STRIPE_KEY = "sk_test_EXAMPLE_KEY"99100# TRUE POSITIVE: Production key in code101STRIPE_KEY = "sk_live_EXAMPLE_PROD_KEY"102```103104## Severity Classification105106- **Critical:** Production API keys (AWS, Stripe live, database passwords), private keys, JWT signing secrets107- **High:** Service tokens (GitHub, GitLab, Slack, SendGrid) that grant significant access108- **Medium:** API keys with limited scope, internal service credentials, publishable keys misidentified as secret109- **Low:** Test/sandbox keys, example/placeholder values, keys in documentation110111## Output Format112113### Finding: SECRET-{NNN}114- **Title:** Hardcoded {key type} in {file}115- **Severity:** Critical | High | Medium | Low116- **Confidence:** 0-100117- **File:** file/path:line118- **Vulnerability Type:** CWE-798 (Hardcoded Credentials) | CWE-321 (Hard-coded Cryptographic Key)119- **Description:** {Service} {key type} found hardcoded in source code.120- **Impact:** Unauthorized access to {service}, data breach, financial loss, account compromise.121- **Remediation:** Move secret to environment variable or secrets manager. Rotate the exposed key immediately.122- **References:** https://cwe.mitre.org/data/definitions/798.html123124## Common False Positives1251261. **Environment variable reads** — `os.getenv("KEY")`, `process.env.KEY` are runtime reads, not hardcoded1272. **Test/sandbox keys** — `sk_test_`, `pk_test_`, keys containing "test", "example", "demo"1283. **Placeholder values** — `"changeme"`, `"your-api-key"`, `"xxx"`, `"TODO"`1294. **Public keys** — SSH public keys, JWT public keys, certificate public keys are not secrets1305. **Hash outputs** — bcrypt hashes, SHA hashes in migration files are not secrets1316. **Base64-encoded non-secrets** — base64 strings that are UI assets, not credentials1327. **Configuration templates** — `.env.example` files with placeholder values