# No default or test accounts in non-test code

- **Pattern:** `ab-002246` (`saas-authentication.password-credential.dev-accounts-removed`)
- **Severity:** info
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002246
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002246)

## Why it matters

Hardcoded default credentials (CWE-798) in seed scripts or initialization code are one of the most targeted attack vectors — automated scanners look for accounts with passwords like 'admin123', 'password', or 'test' within minutes of a deployment. OWASP A07 includes default credentials as a named authentication failure. PCI-DSS v4.0 Req-2.2.2 requires that vendor default accounts are either removed/disabled or have their default passwords changed per Req-8.3.6. A seed script that creates an admin account without an environment guard may silently run in production during a migration or initial deploy, creating a fully privileged account with a known, public password.

## Severity rationale

Info because default credentials require an attacker to know or guess the account exists, but their presence in production is a high-confidence finding that warrants immediate remediation.

## Remediation

Gate any seed script that creates user accounts behind a strict environment check and use environment variables for any credentials that must exist in non-production environments:

```ts
// prisma/seed.ts
if (process.env.NODE_ENV === 'production') {
  console.log('Skipping seed in production')
  process.exit(0)
}

// Never use hardcoded passwords — even in dev:
const adminPassword = process.env.DEV_ADMIN_PASSWORD
if (!adminPassword) throw new Error('DEV_ADMIN_PASSWORD not set')
await db.user.create({ data: { email: 'admin@dev.local', passwordHash: await bcrypt.hash(adminPassword, 12) } })
```

Add a CI grep step in `.github/workflows/` to fail the build if hardcoded passwords like `admin123`, `password`, or `test` appear in non-test source files. Remove any existing default accounts from migration SQL before the next deploy.

## Detection

- **ID:** `dev-accounts-removed`
- **Severity:** `info`
- **What to look for:** Search source code and migration/seed files for hardcoded test users, default admin credentials, or development-only accounts. Look for seed scripts that create accounts with predictable passwords. Check for any code that creates a default admin account if no users exist (a common bootstrapping pattern that can be dangerous in production). Count all instances found and enumerate each.
- **Pass criteria:** No hardcoded user credentials or default account creation logic in non-test source files. Seed scripts that create users are gated behind environment checks (`if (process.env.NODE_ENV !== 'production')`). At least 1 implementation must be confirmed.
- **Fail criteria:** Default admin accounts, test user seeding code, or hardcoded credentials exist in source files that run in production environments.
- **Skip (N/A) when:** No user authentication. Signal: no auth library, no user table.
- **Detail on fail:** `"Database seed at prisma/seed.ts creates admin user with password 'admin123' with no environment guard — this seed may run in production"`.
- **Remediation:** Default credentials are frequently targeted by automated scanners. Ensure seed scripts include environment guards, and remove any hardcoded credentials from non-test code.
 Check `src/` seed scripts and remove any hardcoded credentials. Add a CI step in `.github/workflows/` to grep for default passwords.

## External references

- cwe CWE-798
- owasp A07
- pci-dss Req-2.2.2

Taxons: placeholder-hygiene, access-control

HTML version: https://auditbuffet.com/patterns/ab-002246
