# No debug logging in production

- **Pattern:** `ab-002307` (`saas-logging.app-logging.no-debug-production`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002307
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002307)

## Why it matters

CWE-779 (Logging of Excessive Data) identifies verbose debug output in production as a logging misconfiguration with real costs: inflated log ingestion bills, slower log shipping, and inadvertent exposure of internal state that debug-level entries often contain. NIST AU-11 covers log retention and volume management — producing debug output in production that you don't need directly increases retention costs without increasing observability value. The secondary risk is that debug output frequently captures internal parameter values, function inputs, and intermediate state that are inappropriate for a production log store. A hardcoded `level: 'debug'` in your logger config means your production environment is behaving like a development instance.

## Severity rationale

Low because debug logging in production inflates cost and occasionally leaks internal state, but does not directly enable attack vectors or data loss.

## Remediation

Control log level through an environment variable so you can raise verbosity for debugging without a code change or redeploy.

```ts
// lib/logger.ts
const logger = pino({
  level: process.env.LOG_LEVEL ?? 'info', // 'debug' in dev, 'info' in prod
})
```

Set `LOG_LEVEL=info` in your production hosting environment (Vercel project settings, Fly.io secrets, Railway variables). Set `LOG_LEVEL=debug` in `.env.local` for local development. Add `LOG_LEVEL=info` to `.env.example` so the convention is documented for other developers.

## Detection

- **ID:** `no-debug-production`
- **Severity:** `low`
- **What to look for:** Enumerate all relevant files and Check logging configuration for how debug-level output is controlled. Look for `LOG_LEVEL` environment variable usage, logger configuration that reads from environment, or hardcoded log level settings. Specifically look for: `level: 'debug'` hardcoded without an environment condition, `logger.debug(...)` calls that would fire in production, or `console.log` / `console.debug` calls that aren't guarded by a development environment check. Also check `.env.example` for a `LOG_LEVEL` variable.
- **Pass criteria:** No more than 0 violations are acceptable. Logger is configured to use `info` level or higher in production, either via environment variable (`LOG_LEVEL=info` in production env) or hardcoded non-debug level. Debug calls are either absent or gated behind an environment check.
- **Fail criteria:** Logger is hardcoded to `debug` level without environment gating, OR no log level configuration exists at all (defaulting to the library's debug-level default).
- **Skip (N/A) when:** No logging library and no meaningful `console.log` usage in server-side code.
- **Detail on fail:** Example: `"pino configured with level: 'debug' hardcoded in lib/logger.ts — will emit verbose debug output in production"` or `"No LOG_LEVEL environment variable; logger defaults to debug level"`
- **Remediation:** Debug-level output in production bloats your log storage (and bills), slows down your application, and can inadvertently expose verbose internal data. Set the log level via environment variable so you can turn it up when debugging without redeploying.

  ```ts
  // lib/logger.ts
  const logger = pino({
    level: process.env.LOG_LEVEL ?? 'info', // debug in dev, info in prod
  })
  ```

  In your hosting platform's production environment variables, set `LOG_LEVEL=info`. In development, set `LOG_LEVEL=debug` in `.env.local`. Add `LOG_LEVEL=info` to your `.env.example` as documentation.

---

## External references

- cwe CWE-779
- nist AU-11
- iso-25010 performance-efficiency

Taxons: observability, cost-efficiency

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