# No debug routes active in production

- **Pattern:** `ab-000270` (`ai-slop-half-finished.dev-artifacts.debug-routes-active`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000270
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000270)

## Why it matters

Debug routes left without environment gates are live attack surface. They commonly dump internal state — full user tables, environment variables, session stores, database query results — to anyone who discovers them. OWASP A05:2021 (Security Misconfiguration) and CWE-489 (Active Debug Code) both cover this: the misconfiguration is shipping development tooling as production infrastructure. Discovery is trivial: common debug path patterns (`/api/debug`, `/api/test`, `/playground`) are in every web scanner wordlist, and AI-generated projects tend to follow identical naming conventions.

## Severity rationale

Medium because the exploitability depends on what data the route exposes, but debug routes in AI projects frequently dump database contents or internal config without authentication.

## Remediation

Either delete the route file entirely, or add an explicit production gate as the first statement in the handler. In `app/api/debug/route.ts` or `app/playground/page.tsx`:

```ts
export async function GET() {
  if (process.env.NODE_ENV === 'production') {
    return new Response(null, { status: 404 })
  }
  // debug logic below
}
```

Prefer deletion over gating — a 404 in prod still confirms the route exists to a scanner. Walk all route files matching `/api/debug`, `/api/test`, `/api/__dev__`, `/api/dev`, `/debug`, `/playground`, and `/dev-tools` path segments and either remove them or verify they are gated at the middleware layer (`src/middleware.ts`) with a hard `NODE_ENV` check.

## Detection

- **ID:** `debug-routes-active`
- **Severity:** `medium`
- **What to look for:** Walk the routing tree. Count all route files (API or page) whose path segments match any of these debug patterns: `/api/debug`, `/api/test`, `/api/__dev__`, `/api/_dev`, `/api/dev`, `/api/__debug__`, `/api/playground`, `/debug`, `/test-page`, `/__dev__`, `/dev-tools`, `/admin/debug`. Also count route files with names matching `**/debug/**`, `**/dev-only/**`, `**/playground/**`. EXCLUDE route files that are gated by middleware checking `NODE_ENV !== 'production'` OR that have explicit 404 returns in production.
- **Pass criteria:** 0 debug routes are reachable in production. Debug routes that are gated by environment checks are acceptable. Report: "Scanned X routes, Y match debug patterns, 0 are reachable in production."
- **Fail criteria:** At least 1 route matches a debug pattern AND has no environment gate.
- **Skip (N/A) when:** Project has 0 route files.
- **Detail on fail:** `"2 debug routes reachable in production: app/api/debug/route.ts (no env guard), app/playground/page.tsx (no env guard)"`
- **Remediation:** Debug routes left in production become attack surface — they often expose internal state, allow arbitrary commands, or bypass auth. Remove them or gate them strictly:

  ```ts
  // Bad: debug route reachable in prod
  // app/api/debug/route.ts
  export async function GET() {
    return Response.json({ users: await prisma.user.findMany() })
  }

  // Good: block in production
  // app/api/debug/route.ts
  export async function GET() {
    if (process.env.NODE_ENV === 'production') {
      return new Response(null, { status: 404 })
    }
    return Response.json({ users: await prisma.user.findMany() })
  }

  // Better: delete the route entirely
  ```

## External references

- cwe CWE-489
- owasp A05

Taxons: placeholder-hygiene, access-control

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