No hardcoded API keys or secrets in source
Why it matters
A sk_live_, AKIA, ghp_, or private-key literal inside committed source code is functionally identical to publishing the credential — git history is forever, and secret-scanning services (GitHub's built-in scanner, TruffleHog, GitGuardian) will find it faster than most teams can. The 2022 Uber breach began with a contractor's GitHub-leaked credential, and GitGuardian's 2024 State of Secrets Sprawl report logged 23.8 million fresh secrets pushed to GitHub across 2023. AI coding tools produce this anti-pattern routinely: asked to "add Stripe", they paste the example key from docs inline; asked to "connect to the database", they inline the connection string. Even git rm doesn't help — the blob stays reachable through history until a full rewrite plus credential rotation. Stripe, AWS, and GitHub all auto-revoke detected keys, so the loud failure mode is service outage; the quiet mode is an attacker finding it first and quietly using it.
Severity rationale
Critical because a hardcoded key is already compromised the moment it hits git — there is no grace period, no mitigation short of rotation, and no way to claw the secret back from archived clones or cached views.
Remediation
Move the secret to an environment variable, delete the literal from source, rotate the credential immediately (assume it is compromised the moment it lands in git history).
Deeper remediation guidance and cross-reference coverage for this check lives in the security-hardening Pro audit — run that after applying this fix for a more exhaustive pass on the same topic.
Detection
- ID:
no-hardcoded-secrets - Severity:
critical - What to look for: Grep source files (excluding
node_modules,.git, build output,.env*) for:sk_live_,sk_test_,rk_live_,pk_live_(Stripe);AIza(Google);AKIA(AWS);ghp_,gho_,ghs_,github_pat_(GitHub);xoxb-,xoxp-(Slack);eyJhbGciOi(JWTs);-----BEGIN RSA PRIVATE KEY-----,-----BEGIN OPENSSH PRIVATE KEY-----. - Pass criteria: Zero matches in any committed source file.
- Fail criteria: Any match, even in comments (comments still ship to the repo).
- Skip (N/A) when: Never — every project should be checked.
- Before evaluating, quote: File path of any match (path only, NEVER the value). If zero, report
"0 matches across N source files searched". - Report even on pass:
"Scanned ~X source files, 0 secret patterns matched". - Detail on fail:
"Hardcoded Stripe secret key in src/lib/payments.ts (sk_live_ pattern)"— never include the actual value. - Remediation: Move to env var, delete the literal, rotate the credential immediately (assume compromised the moment it lands in git history).
Taxons
History
- 2026-04-22·v1.0.0·Initial import from project-snapshot via Phase 8.1 bundling·by phase-8-1-bundle-project-snapshot
- 2026-04-22·v2.0.0·Phase 9 consequence-first restructure — moved to new section slug, added news/incident references, severity reviewed.·by phase-9-stack-scan-v3
- 2026-04-25·v2.0.1·v3.1.0 pre-ship trim — prose compression for under-80K MCP cap; merged overlapping Fail-criteria / Do-NOT-pass-when sections; compressed enumeration prose; one remediation example per pattern. No semantic change; anti-sycophancy guards preserved.·by phase-9-1-stack-scan-v3-1