# No fallback admin credentials in authentication code

- **Pattern:** `ab-000260` (`ai-slop-half-finished.hardcoded-test-data.fallback-admin-credentials`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000260
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000260)

## Why it matters

Fallback admin credentials are a silent authentication backdoor. When a request arrives with an empty or malformed body, the OR-expression resolves to the hardcoded value — and the code proceeds to look up and authenticate a real admin account. An attacker who sends an empty POST to the login endpoint gets in as admin. This maps to OWASP A07:2021 (Identification and Authentication Failures) and CWE-1188 (Insecure Default Initialization): the default is not 'reject unauthenticated request' but 'log in as administrator.' No rate limit or firewall rule compensates for this; the bypass is baked into application logic.

## Severity rationale

Critical because a single unauthenticated HTTP request with an empty body can elevate to admin access, bypassing all authentication controls entirely.

## Remediation

Fail loudly on missing credentials at the route boundary — never fall through to a default email or password. In your login handler (`src/app/api/login/route.ts` or equivalent), replace every OR-fallback with explicit Zod validation:

```ts
import { z } from 'zod'

const LoginSchema = z.object({
  email: z.string().email(),
  password: z.string().min(1),
})

export async function POST(req: Request) {
  const body = await req.json()
  const parsed = LoginSchema.safeParse(body)
  if (!parsed.success) {
    return Response.json({ error: 'Invalid credentials' }, { status: 400 })
  }
  const { email, password } = parsed.data
  // No fallback, no default — explicit rejection only
}
```

Audit every file that reads `req.body.email`, `req.body.password`, or equivalent session fields and remove all `||` and `??` fallbacks to credential strings.

## Detection

- **ID:** `fallback-admin-credentials`
- **Severity:** `critical`
- **What to look for:** Walk all source files for OR-fallback patterns containing admin/test credentials. Before evaluating, extract and quote each OR-fallback expression. Count all occurrences of these patterns: `X || 'admin@admin.com'`, `X || 'admin@localhost'`, `X || 'test@test.com'`, `X || 'admin@example.com'`, `X || 'admin'` (where X is a variable), `X ?? 'admin@...'`, `X || "password"`, `X || "admin123"`, `X || "123456"`, `X || "password123"`, `X || "letmein"`. Also count default parameters: `function(email = 'admin@admin.com')`, `function(password = 'password123')`. Also count fallback assignments in session/user-creation code: `const email = req.body.email || 'admin@...'`, `const user = { email: body.email || 'admin@...', role: 'admin' }`.
- **Pass criteria:** 0 fallback admin-credential patterns in source code. Report: "Scanned X source files, 0 fallback admin credentials found."
- **Fail criteria:** At least 1 OR-fallback or default parameter pattern uses admin credentials, test passwords, or "bypass" values.
- **Do NOT pass when:** The fallback is conditionally gated on `NODE_ENV === 'development'` but the condition wraps only the value, not the surrounding auth check — the admin email still ends up in the session lookup path.
- **Skip (N/A) when:** Project has 0 non-test source files.
- **Cross-reference:** For deeper authentication security, the SaaS Authentication audit (`saas-authentication`) covers session and credential flows in depth.
- **Detail on fail:** `"2 fallback admin credentials: 'const email = req.body.email || \"admin@admin.com\"' in src/app/api/login/route.ts (line 12), 'const user = { email: body.email ?? \"admin@example.com\" }' in src/lib/session.ts (line 34)"`
- **Remediation:** Fallback admin credentials are a security backdoor — if the request body is empty or malformed, the code silently logs in as admin. Fix by failing loudly on missing credentials:

  ```ts
  // Bad: silent admin bypass
  const email = req.body.email || 'admin@admin.com'
  const user = await findUserByEmail(email)

  // Good: explicit validation, no fallback
  const { email } = req.body
  if (!email) {
    return Response.json({ error: 'Email required' }, { status: 400 })
  }
  const user = await findUserByEmail(email)
  ```

  Use a validation schema (Zod, Yup) to enforce required fields at the route boundary.

## External references

- cwe CWE-1188
- cwe CWE-287
- owasp A07

Taxons: placeholder-hygiene, access-control

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