Hardcoded secrets in source code are the most common high-severity finding in AI-built projects: the model fills in a working API key to make the code run, and the developer ships it without noticing. A Stripe secret key (sk_live_) hardcoded in lib/stripe.ts gives anyone with repo read access the ability to create charges, refund transactions, or read customer data. A hardcoded JWT secret lets an attacker forge authentication tokens. OWASP A07 (Identification and Authentication Failures) and CWE-798 (Use of Hard-coded Credentials) directly describe this class of defect. PCI-DSS 4.0 Req 8.6.2 explicitly prohibits hard-coded credentials in any system component. Secrets in git history must be rotated even after removal from the code — the history is permanent.
Critical because a hardcoded secret key gives anyone with repository read access full API-level access to the associated service, often with no rate limiting or geo restriction.
Move every secret literal to an environment variable reference. The fix is mechanical — find the literal, move it to .env.local, and reference it via process.env.
// Before (DANGEROUS — rotate this key immediately):
const stripe = new Stripe('sk_live_abc123...')
// After (SAFE):
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
After moving secrets to environment variables: rotate every exposed key immediately — assume any secret that ever appeared in your git history has been seen, regardless of whether the repo was private. Use git log -S 'sk_live_' to confirm the secret is gone from all commits; if it isn't, you need a history rewrite (git filter-repo).
ID: security-headers.basic-hygiene.no-hardcoded-secrets
Severity: critical
What to look for: Count all source code files searched and enumerate any hardcoded secret patterns found: API keys, tokens, passwords, connection strings. Only flag secret/private keys — not public keys that are intentionally embedded client-side. Look for:
sk_live_, sk_test_ — flag these. Do NOT flag Stripe publishable keys (pk_live_, pk_test_) — these are designed to be public and are safely embedded in client-side code.ghp_, gho_, ghu_AKIA (access key IDs) combined with a secret key valuepassword = "...", secret = "...", or apiKey = "..." with literal string values (not environment variable references)_secret_ in any API key patternkey, secret, token, password, or credentialImportant: Only flag literal string values in source code. References to process.env.SECRET_KEY or import.meta.env.VITE_SECRET are correct and must NOT be flagged.
Before evaluating: List each directory and file pattern searched (e.g., "Searched src/, lib/, app/, pages/, config/ for patterns: sk_live_, sk_test_, ghp_, AKIA, password =, secret =, apiKey ="). For any flagged item, quote the variable name and assignment pattern (not the actual secret value). Example: "Found const stripeKey = 'sk_test_...' in lib/stripe.ts line 4."
Pass criteria: 0 hardcoded secrets or private keys found in source code after searching at least 3 source directories. All secrets are accessed via environment variables (process.env.*, import.meta.env.*). Publishable/public keys embedded in client code are acceptable.
Fail criteria: At least 1 hardcoded secret key, private API key, password, or credential found as a literal string in source code files.
Do NOT pass when: Absence of evidence alone is insufficient — actively search all source files, config files, and test fixtures for secret patterns. A cursory scan of only top-level files is not sufficient.
Skip (N/A) when: Never — this check always applies.
Detail on fail: "Hardcoded Stripe key found in lib/stripe.ts: sk_live_... value assigned directly instead of using process.env" or "Database connection string with credentials hardcoded in db/config.ts". Never include the actual secret value in the detail string.
Remediation: Secrets in source code are the most common security issue in AI-built projects. Move all secrets to environment variables:
// Before (DANGEROUS):
const stripe = new Stripe('sk_live_abc123...')
// After (SAFE):
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
After fixing, rotate any exposed keys immediately — they should be considered compromised if they were ever in your git history. For application-level security analysis including auth flows and authorization, the SaaS Readiness Pack covers this in depth.