Rule
Remove debugging and temporary code before commits.
Code that bypasses logic, outputs debug info,
or stops execution for debugging was likely
left behind accidentally during development.
Supported languages: 45+Introduction
Debugging code, console.log() statements, commented-out logic, hardcoded test values, or debugger breakpoints, ships to production more often than most teams admit. These artifacts expose internal application state, create performance overhead, and signal to attackers which parts of your codebase were problematic during development. What starts as temporary code for troubleshooting becomes a permanent security risk if not removed before deployment.
Why it matters
Security implications: Debug code in production often logs sensitive data like user credentials, API keys, or PII that shouldn't reach production logs.
A console.log(user) statement might dump an entire user object including session tokens into browser console or server logs accessible to support staff or log aggregation tools. This is one of the most common code security vulnerabilities that automated code review tools catch.
Performance impact: Excessive console logging creates I/O bottleneck. A high-traffic endpoint logging request payloads can degrade response times by 15-30ms per request and bloat log storage costs. The performance impact of logging in Node.js production environments compounds quickly at scale.
Code maintainability: Temporary code commits like if (true) return; or
// TODO: fix later bypass business logic and create confusion for future maintainers. They represent technical debt with no documentation trail.
Attack surface expansion: Debugger statements and verbose error logging reveal stack traces, file paths, dependency versions, and internal logic flow, information useful for reconnaissance during targeted attacks.
Code examples
❌ Non-compliant:
async function processPayment(userId, amount) {
console.log('Processing payment:', { userId, amount });
const user = await db.users.findById(userId);
console.log('User data:', user); // Logs email, tokens, everything
debugger;
const result = await paymentGateway.charge({
userId: user.id,
amount: amount
});
console.log('Gateway response:', result);
return result;
}
Why this is unsafe: Console statements log PII (Personally Identifiable Information) and authentication tokens to production logs. The commented debugger creates ambiguity about execution paths. All of this data is accessible to anyone with log access and provides attackers with reconnaissance data.
✅ Compliant:
async function processPayment(userId, amount) {
const user = await db.users.findById(userId);
if (!user) {
throw new PaymentError('User not found');
}
const result = await paymentGateway.charge({
userId: user.id,
amount: amount
});
await auditLog.record({
event: 'PAYMENT_PROCESSED',
userId: userId,
transactionId: result.transactionId
});
return result;
}Why this is safe: Structured logging replaces console.log with proper audit trails that capture business events without exposing sensitive user data. No debug statements exist. Logic flows linearly without conditional bypasses. Audit logs are centralized, access-controlled, and contain only necessary context for compliance and debugging.
Conclusion
Debug code in production isn't a minor issue, it's a security vulnerability, performance liability, and maintenance burden. Following secure code review best practices means catching these issues before they reach your main branch. Automated code quality rules should prevent debugging code from reaching version control, let alone production. The key is having the right tooling to catch these issues before they merge.
.avif)
