Hardcoded API Key or Secret
Hardcoded API keys, tokens, and secrets committed to source code, where anyone with access to the repo or its git history can read them.
What this rule detects
VC001 finds string literals that look like real credentials: AWS access keys (AKIA...), Stripe keys (sk_live_/sk_test_/pk_live_/pk_test_), legacy-format OpenAI keys, Supabase anon or service-role keys assigned in code, private-key blocks, database URLs with an embedded password, and long values assigned to names like apiKey, token, secret, password or *_SECRET / *_TOKEN / *_KEY. GitHub and Slack tokens and other vendor-specific formats are separate rules on paid plans. A separate entropy check (not VC001) flags random-looking strings that match no known format. Test-mode keys in test files are reported at low severity; live keys are always graded.
Vulnerable vs. safe code
// .env values committed to source — visible in git history forever.
const stripe = new Stripe("sk_live_51HxYzL2eZvKYlo2C9X8fG7H8JkLm...");
const openai = new OpenAI({
apiKey: "sk-proj-abc123def456ghi789jkl012mno345pqr678",
});// Read from environment at runtime. Never committed.
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY!,
});
// In your repo: .env (gitignored), .env.example (committed, no values).
// In production: secrets injected by Vercel/Railway/Fly/AWS Secrets Manager.If you've already committed a key, rotating it is mandatory — `git rm` doesn't help because the value still exists in history. Treat any key that ever lived in a public commit as compromised.
About A07:2021 — Identification & Auth Failures
Authentication is hard to get right and easy to get subtly wrong. Common failures: storing passwords with weak hashes, not invalidating sessions on logout, allowing unlimited login attempts, accepting JWTs without verifying the signature. AI tools sometimes invent auth code that looks correct but skips the verification step.
Impact: When auth breaks, every user account is potentially compromised. Brute force on login becomes credential stuffing at scale. Session fixation lets one user steal another's session. Accepted-without-verification JWTs let anyone forge any identity.
How to fix it: Use a battle-tested auth provider (Clerk, Auth0, NextAuth, AWS Cognito) instead of building from scratch. If you must build it: bcrypt or argon2 for passwords, account lockout after N failed attempts, MFA support, signed and expiring session tokens, full JWT signature verification.
Common patterns in this category:
- JWT decoded without verifying the signature
- No account lockout after repeated failed logins
- Passwords hashed with MD5 or SHA-1 instead of bcrypt/argon2
- Session IDs that don't rotate on login or privilege change
- Password reset tokens that don't expire or aren't single-use
Framework mapping
Findings from this rule map to the following framework controls. This is an informational mapping, not an audit, certification, or attestation.
See the full compliance coverage page for how every rule maps to OWASP Top 10 and CWE, and which rules also carry informational SOC 2 and ISO 27001 cross-references.
Scan your code for VC001
Free, no signup: paste code or upload a file, or run npx xploitscan@latest scan . The free scan runs 30 core rules; paid plans run all 223.