Structured logging library is used
Why it matters
CWE-778 (Insufficient Logging) and OWASP A09 (Security Logging & Monitoring Failures) both identify the absence of structured, machine-readable logs as a root cause of failed incident detection. When logging is ad-hoc console.log calls, production log platforms cannot parse, index, or alert on log data — a single exception swallowed in unstructured output can leave a breach undetected for days. NIST AU-2 requires that audit-relevant events be logged in a format that supports analysis; plain-text console output fails that bar. Structured JSON logs (with timestamp, level, message, and context fields) are what log aggregation platforms like Better Stack, Axiom, and Datadog index and query against.
Severity rationale
High because unstructured logs disable the entire observability pipeline — alerting, search, and incident response all depend on parseable log entries.
Remediation
Replace ad-hoc console.log calls with a central structured logger. For Next.js, Pino is the standard choice — fast, JSON-native, and supported by all major log platforms.
Create lib/logger.ts:
import pino from 'pino'
const logger = pino({
level: process.env.LOG_LEVEL ?? 'info',
...(process.env.NODE_ENV === 'development'
? { transport: { target: 'pino-pretty' } }
: {})
})
export default logger
Then replace every console.log(...) in server-side code with logger.info(...), logger.error(...), etc. Run a search for console.log in app/api/ and lib/ to find all call sites.
Detection
-
ID:
structured-logging -
Severity:
high -
What to look for: Enumerate all relevant files and Check
package.jsonfor structured logging libraries: winston, pino, bunyan, consola, loglevel, @opentelemetry/api, @logtail/node, axiom-node, or any cloud provider logging SDK. Also check for a custom logger module (lib/logger.*,utils/logger.*) that wrapsconsolewith structured output (JSON format with level, timestamp, and message fields). Plainconsole.logscattered throughout the codebase without a wrapper does not pass. Quote the exact code pattern or configuration value found. -
Pass criteria: At least 1 conforming pattern must exist. A structured logging library is present in dependencies, OR a custom logger module exists that produces JSON-formatted log entries with at minimum a timestamp, level, and message field. Usage of the logger is visible in server-side code (API routes, middleware, server components/actions).
-
Fail criteria: No structured logging library found; logging is exclusively raw
console.log/console.errorcalls spread throughout the codebase with no central logger abstraction. A partial or incomplete implementation does not count as pass. -
Skip (N/A) when: Project is a static site with no server-side code — no API routes, server components, server actions, or backend logic of any kind. Signal: no
app/api/orpages/api/directory, no server functions, framework reports as static-only. -
Cross-reference: For security evaluation of log data handling and access controls, the Security Headers audit covers information exposure and data protection.
-
Detail on fail: List the logging approach found. Example:
"No structured logging library in package.json; logging is ad-hoc console.log calls found in 12+ API route files with no central logger module" -
Remediation: Ad-hoc
console.logcalls produce unstructured output that is hard to search, filter, and alert on in production log systems. A structured logger produces machine-readable JSON entries that platforms like Better Stack, Axiom, Datadog, and Sentry can index and query.For a Next.js project, install Pino (fast, JSON-native):
npm install pino pino-prettyCreate a central logger at
lib/logger.ts:import pino from 'pino' const logger = pino({ level: process.env.LOG_LEVEL || 'info', ...(process.env.NODE_ENV === 'development' ? { transport: { target: 'pino-pretty' } } : {}) }) export default loggerThen import and use
logger.info(...),logger.error(...)instead ofconsole.log.Verify by running the app and confirming log output is JSON in production mode.
External references
- cwe · CWE-778 — Insufficient Logging
- owasp:2021 · A09 — Security Logging and Monitoring Failures
- nist:rev5 · AU-2 — Event Logging
- iso-25010:2011 · maintainability
Taxons
History
- 2026-04-18·v1.0.0·Initial import from saas-logging·automated