Unguarded console.log calls in production code expose internal data structures — user objects, API responses, internal state — to browser consoles and server logs. CWE-532 (Insertion of Sensitive Information into Log File) applies when logged objects include user data, tokens, or application secrets. Beyond the data exposure risk, console.log in server-side code that runs on every request floods logs with noise, making real errors and security incidents harder to detect. AI-generated codebases accumulate debug logs that were never removed before shipping.
Low because `console.log` in production primarily causes data leakage and log noise rather than direct security exploitation, though CWE-532 applies when logged objects contain sensitive data.
Add an ESLint rule to flag production console calls:
"no-console": ["warn", { "allow": ["warn", "error"] }]
Replace debug logging with a structured logger that is environment-aware:
// lib/logger.ts
export const logger = {
info: (msg: string, data?: object) => {
if (process.env.NODE_ENV !== 'production') console.log(msg, data)
// In production: send to your logging service
},
error: (msg: string, error?: unknown) => console.error(msg, error)
}
Server-side route handlers should never call console.log on every request — use structured logging with sampling instead.
ID: code-maintainability.code-hygiene.no-console-logs
Severity: low
What to look for: Search source files for console.log, console.debug, console.warn, and console.error calls in production code paths. Acceptable uses: console.error in catch blocks for error logging (until a proper logger is set up), console.warn with process.env.NODE_ENV !== 'production' guards. Not acceptable: console.log calls left from debugging, console.log in server-side code that runs on every request.
Pass criteria: Count every console.log and console.debug call in production code paths (exclude test files and environment-guarded calls). No more than 4 unguarded console.log or console.debug calls in production source code. console.error in catch blocks is acceptable. Console calls guarded by process.env.NODE_ENV !== 'production' are acceptable. Report the count: "Found X unguarded console.log/debug calls across Y source files."
Fail criteria: 5 or more console.log or console.debug calls found in production source code (not in test files, not environment-guarded).
Skip (N/A) when: The project has fewer than 5 source files. Signal: fewer than 5 source files.
Detail on fail: "12 console.log calls found in production code: 4 in lib/api.ts, 3 in components/DataTable.tsx, 5 in app/api/ route handlers. These log to user browser consoles and server output on every request." or "console.log statements in API route handlers expose internal data structure to server logs."
Remediation: console.log left in production code leaks internal data structures to browser consoles and fills server logs with noise, making real errors harder to find.
Add an ESLint rule to catch console calls:
"no-console": ["warn", { "allow": ["warn", "error"] }]
For server-side logging, replace with a structured logger:
// lib/logger.ts
export const logger = {
info: (msg: string, data?: object) => {
if (process.env.NODE_ENV !== 'production') console.log(msg, data)
// In production: send to your logging service
},
error: (msg: string, error?: unknown) => console.error(msg, error)
}