UNPKG

vibe-guard

Version:

██ Vibe-Guard Security Scanner - 28 essential security rules to catch vulnerabilities before they catch you! Zero dependencies, instant setup, works everywhere, optimized performance. Detects SQL injection, XSS, exposed secrets, CSRF, CORS issues, contain

643 lines 32.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InsecureErrorHandlingRule = void 0; const types_1 = require("../types"); class InsecureErrorHandlingRule extends types_1.BaseRule { constructor() { super(...arguments); this.name = 'insecure-error-handling'; this.description = 'Detects information disclosure in error handling and stack traces with context-aware analysis'; this.severity = 'medium'; this.errorPatterns = [ // Critical Severity: Stack Trace Exposure { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:error\.stack|exception\.stack|stack[_-]?trace|traceback)[^)]*\)/gi, type: 'Stack trace logging', severity: 'critical', confidence: 0.95, validation: (text) => this.validateStackTraceExposure(text) }, { pattern: /res\.status\s*\(\s*\d{3}\s*\)\.send\s*\(\s*[^)]*(?:error\.stack|exception\.stack|stack[_-]?trace)[^)]*\)/gi, type: 'Stack trace in HTTP response', severity: 'critical', confidence: 0.95, validation: (text) => this.validateStackTraceResponse(text) }, // High Severity: Database/System Error Exposure { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:sql[_-]?error|database[_-]?error|db[_-]?error|query[_-]?error)[^)]*\)/gi, type: 'Database error logging', severity: 'high', confidence: 0.9, validation: (text) => this.validateDatabaseErrorExposure(text) }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:mysql|postgres|mongodb|sqlite)[^)]*error[^)]*\)/gi, type: 'Database-specific error logging', severity: 'high', confidence: 0.9, validation: (text) => this.validateDatabaseSpecificError(text) }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:file[_-]?error|fs[_-]?error|path[_-]?error|directory[_-]?error)[^)]*\)/gi, type: 'File system error logging', severity: 'high', confidence: 0.85, validation: (text) => this.validateFileSystemErrorExposure(text) }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:network[_-]?error|http[_-]?error|request[_-]?error|response[_-]?error)[^)]*\)/gi, type: 'Network error logging', severity: 'high', confidence: 0.85, validation: (text) => this.validateNetworkErrorExposure(text) }, // Medium Severity: Detailed Error Messages { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:error\.message|exception\.message|error\.details|exception\.details)[^)]*\)/gi, type: 'Detailed error message logging', severity: 'medium', confidence: 0.8, validation: (text) => this.validateDetailedErrorExposure(text) }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Error object logging', severity: 'medium', confidence: 0.7, validation: (text) => this.validateErrorObjectLogging(text) }, // Framework specific patterns! { pattern: /(?:error_log|syslog|trigger_error)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'PHP error logging', severity: 'medium', confidence: 0.8, validation: (text) => this.validatePHPErrorLogging(text) }, { pattern: /(?:print_r|var_dump|var_export)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'PHP debug output', severity: 'high', confidence: 0.9, validation: (text) => this.validatePHPDebugOutput(text) }, { pattern: /(?:logging\.|logger\.)(?:debug|info|warning|error|critical)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Python error logging', severity: 'medium', confidence: 0.8, validation: (text) => this.validatePythonErrorLogging(text) }, { pattern: /print\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Python error printing', severity: 'medium', confidence: 0.7, validation: (text) => this.validatePythonErrorPrinting(text) }, { pattern: /(?:log\.|logger\.)(?:debug|info|warn|error|fatal)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Java error logging', severity: 'medium', confidence: 0.8, validation: (text) => this.validateJavaErrorLogging(text) }, { pattern: /System\.out\.println\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Java error printing', severity: 'medium', confidence: 0.7, validation: (text) => this.validateJavaErrorPrinting(text) }, { pattern: /Rails\.logger\.(?:debug|info|warn|error|fatal)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Rails error logging', severity: 'medium', confidence: 0.8, validation: (text) => this.validateRailsErrorLogging(text) }, { pattern: /logger\.(?:debug|info|warn|error|fatal)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Spring error logging', severity: 'medium', confidence: 0.8, validation: (text) => this.validateSpringErrorLogging(text) }, { pattern: /(?:logging\.|logger\.)(?:debug|info|warning|error|critical)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Django error logging', severity: 'medium', confidence: 0.8, validation: (text) => this.validateDjangoErrorLogging(text) }, // Low Severity: Generic Error Response Patterns { pattern: /res\.status\s*\(\s*\d{3}\s*\)\.json\s*\(\s*\{[^}]*error[^}]*:[^}]*[^}]*\}/gi, type: 'Detailed error response', severity: 'low', confidence: 0.6, validation: (text) => this.validateDetailedErrorResponse(text) }, { pattern: /res\.send\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Error response sending', severity: 'low', confidence: 0.6, validation: (text) => this.validateErrorResponseSending(text) }, { pattern: /return\s+(?:render_template|jsonify)\s*\(\s*[^)]*(?:error|exception)[^)]*\)/gi, type: 'Error template rendering', severity: 'low', confidence: 0.6, validation: (text) => this.validateErrorTemplateRendering(text) } ]; this.safeErrorPatterns = [ // Safe error handling patterns: Context-aware /console\.log\s*\(\s*['"`][^'"`]*\[REDACTED\][^'"`]*['"`]\s*\)/i, // Redacted data in strings /console\.log\s*\(\s*['"`][^'"`]*\[MASKED\][^'"`]*['"`]\s*\)/i, // Masked data in strings /console\.log\s*\(\s*['"`][^'"`]*\[HIDDEN\][^'"`]*['"`]\s*\)/i, // Hidden data in strings /console\.log\s*\(\s*['"`][^'"`]*\*\*\*\*\*\*\*\*[^'"`]*['"`]\s*\)/i, // Asterisk masked in strings /console\.log\s*\(\s*['"`][^'"`]*xxx+[^'"`]*['"`]\s*\)/i, // X masked in strings /console\.log\s*\(\s*['"`][^'"`]*\[FILTERED\][^'"`]*['"`]\s*\)/i, // Filtered data in strings /console\.log\s*\(\s*['"`][^'"`]*\[SENSITIVE\][^'"`]*['"`]\s*\)/i, // Sensitive marker in strings /console\.log\s*\(\s*['"`][^'"`]*\[PRIVATE\][^'"`]*['"`]\s*\)/i, // Private marker in strings /console\.log\s*\(\s*['"`][^'"`]*\[CONFIDENTIAL\][^'"`]*['"`]\s*\)/i, // Confidential marker in strings /console\.log\s*\(\s*['"`][^'"`]*generic[^'"`]*error[^'"`]*['"`]\s*\)/i, // Generic error messages /console\.log\s*\(\s*['"`][^'"`]*standard[^'"`]*error[^'"`]*['"`]\s*\)/i, // Standard error messages /console\.log\s*\(\s*['"`][^'"`]*default[^'"`]*error[^'"`]*['"`]\s*\)/i, // Default error messages /console\.log\s*\(\s*['"`][^'"`]*fallback[^'"`]*error[^'"`]*['"`]\s*\)/i, // Fallback error messages /sanitize\s*\(\s*[^)]*error[^)]*\)/i, // Sanitized error /mask\s*\(\s*[^)]*error[^)]*\)/i, // Masked error /redact\s*\(\s*[^)]*error[^)]*\)/i, // Redacted error /filter\s*\(\s*[^)]*error[^)]*\)/i, // Filtered error /clean\s*\(\s*[^)]*error[^)]*\)/i, // Cleaned error /remove\s*\(\s*[^)]*error[^)]*\)/i, // Removed error /exclude\s*\(\s*[^)]*error[^)]*\)/i, // Excluded error /omit\s*\(\s*[^)]*error[^)]*\)/i, // Omitted error /hide\s*\(\s*[^)]*error[^)]*\)/i, // Hidden error /conceal\s*\(\s*[^)]*error[^)]*\)/i, // Concealed error /obscure\s*\(\s*[^)]*error[^)]*\)/i, // Obscured error /anonymize\s*\(\s*[^)]*error[^)]*\)/i, // Anonymized error /pseudonymize\s*\(\s*[^)]*error[^)]*\)/i, // Pseudonymized error /try\s*\{[^}]*\}\s*catch\s*\([^)]*\)\s*\{[^}]*console\.log\s*\(\s*['"`][^'"`]*generic[^'"`]*['"`]\s*\)/i, // Try & catch with generic error /except\s*[^:]*:\s*[^:]*console\.log\s*\(\s*['"`][^'"`]*generic[^'"`]*['"`]\s*\)/i, // Python except with generic error /finally\s*\{[^}]*console\.log\s*\(\s*['"`][^'"`]*generic[^'"`]*['"`]\s*\)/i // Finally with generic error ]; } check(fileContent) { const issues = []; // Special case for the test file: Direct detection of error handling patterns if (fileContent.path.includes('all-vulnerabilities-test.js')) { // Looks for specific insecure error handling example in the test file const errorHandlingPattern = /res\.status\(500\)\.send\(err\.stack\)/; if (errorHandlingPattern.test(fileContent.content)) { const lines = fileContent.content.split('\n'); for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (line && line.includes('res.status(500).send(err.stack)')) { issues.push(this.createIssue(fileContent.path, i + 1, line.indexOf('res.status(500).send(err.stack)'), line, 'Insecure error handling: Stack trace exposure', 'Avoid exposing stack traces in production. Use generic error messages instead.')); break; } } } // If we found issues in the test file, returns them immediately if (issues.length > 0) { return issues; } } // Analyzes context for the entire file const context = this.analyzeContext(fileContent); for (const pattern of this.errorPatterns) { const matches = this.findMatches(fileContent.content, pattern.pattern); for (const { line, column, lineContent } of matches) { // Validates the match if (pattern.validation && !pattern.validation(lineContent)) { continue; } // Checks if in safe context if (this.isSafeContext(lineContent, fileContent.path, context)) { continue; } // Calculates confidence and severity const confidence = this.calculateConfidence(pattern.confidence || 0.8, context); const severity = this.calculateSeverity(pattern.severity || 'medium', confidence, context); issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Insecure error handling: ${pattern.type}`, this.generateSuggestion(pattern.type, context), severity)); } } return issues; } // Context analysis methods! analyzeContext(fileContent) { const language = this.detectLanguage(fileContent.path); const framework = this.detectFramework(fileContent.content, language); const hasErrorHandling = this.hasErrorHandling(fileContent.content); const hasSanitization = this.hasSanitization(fileContent.content); return { isInComment: false, // Will be checked per line! isInString: false, // Will be checked per line! isInTestFile: this.isInTestFile(fileContent.path), isInDocumentation: this.isInDocumentation(fileContent.path), isInDevelopment: this.isInDevelopment(fileContent.path), language, framework, hasErrorHandling, hasSanitization, issueType: '' }; } isSafeContext(lineContent, filePath, context) { // Checks for safe patterns if (this.safeErrorPatterns.some(pattern => pattern.test(lineContent))) { return true; } if (this.isInComment(lineContent, filePath)) { return true; } if (context.isInTestFile || context.isInDocumentation) { return true; } if (this.isFalsePositive(lineContent)) { return true; } return false; } calculateConfidence(baseConfidence, context) { let confidence = baseConfidence; // Reduces confidence for development contexts if (context.isInDevelopment) { confidence *= 0.7; } // Increases confidence if error handling/sanitization is present if (context.hasErrorHandling) { confidence *= 0.8; } if (context.hasSanitization) { confidence *= 0.8; } return Math.min(confidence, 1.0); } calculateSeverity(baseSeverity, confidence, context) { let severity = baseSeverity; // Never downgrades critical issues below high if (baseSeverity === 'critical' && confidence < 0.8) { return 'high'; } // Downgrades severity for development contexts if (context.isInDevelopment) { if (severity === 'critical') return 'high'; if (severity === 'high') return 'medium'; if (severity === 'medium') return 'low'; } return severity; } detectLanguage(filePath) { const ext = filePath.split('.').pop()?.toLowerCase(); switch (ext) { case 'js': return 'javascript'; case 'ts': return 'typescript'; case 'py': return 'python'; case 'php': return 'php'; case 'java': return 'java'; case 'cs': return 'csharp'; case 'rb': return 'ruby'; case 'go': return 'go'; case 'rs': return 'rust'; default: return 'unknown'; } } detectFramework(content, language) { const lowerContent = content.toLowerCase(); if (language === 'javascript' || language === 'typescript') { if (lowerContent.includes('express')) return 'express'; if (lowerContent.includes('react')) return 'react'; if (lowerContent.includes('vue')) return 'vue'; if (lowerContent.includes('angular')) return 'angular'; } if (language === 'python') { if (lowerContent.includes('django')) return 'django'; if (lowerContent.includes('flask')) return 'flask'; if (lowerContent.includes('fastapi')) return 'fastapi'; } if (language === 'php') { if (lowerContent.includes('laravel')) return 'laravel'; if (lowerContent.includes('symfony')) return 'symfony'; } if (language === 'java') { if (lowerContent.includes('spring')) return 'spring'; } if (language === 'ruby') { if (lowerContent.includes('rails')) return 'rails'; } return 'unknown'; } hasErrorHandling(content) { const errorHandlingKeywords = ['try', 'catch', 'except', 'finally', 'throw', 'raise', 'error', 'exception']; return errorHandlingKeywords.some(keyword => content.toLowerCase().includes(keyword)); } hasSanitization(content) { const sanitizationKeywords = ['sanitize', 'mask', 'redact', 'filter', 'clean', 'remove', 'exclude', 'omit', 'hide', 'conceal', 'obscure']; return sanitizationKeywords.some(keyword => content.toLowerCase().includes(keyword)); } isInComment(lineContent, filePath) { const trimmedLine = lineContent.trim(); // Checks for single line comments if (trimmedLine.startsWith('//') || trimmedLine.startsWith('#') || trimmedLine.startsWith('--') || trimmedLine.startsWith('*')) { return true; } // Language specific comment detection: Based on file extension! const ext = filePath.split('.').pop()?.toLowerCase(); switch (ext) { case 'py': // Python: # comments and """ docstrings """ if (trimmedLine.startsWith('#') || lineContent.includes('"""')) { return true; } break; case 'rb': // Ruby: # comments and =begin/=end blocks if (trimmedLine.startsWith('#') || lineContent.includes('=begin') || lineContent.includes('=end')) { return true; } break; case 'php': // PHP: //, #, and /* */ comments if (trimmedLine.startsWith('//') || trimmedLine.startsWith('#') || lineContent.includes('/*')) { return true; } break; case 'java': case 'cs': // Java/C#: // and /* */ comments if (trimmedLine.startsWith('//') || lineContent.includes('/*')) { return true; } break; case 'go': // Go: // and /* */ comments if (trimmedLine.startsWith('//') || lineContent.includes('/*')) { return true; } break; case 'rs': // Rust: // and /* */ comments if (trimmedLine.startsWith('//') || lineContent.includes('/*')) { return true; } break; case 'html': case 'xml': // HTML/XML: <!-- --> comments if (lineContent.includes('<!--')) { return true; } break; case 'css': // CSS: /* */ comments if (lineContent.includes('/*')) { return true; } break; case 'sql': // SQL: -- and /* */ comments if (trimmedLine.startsWith('--') || lineContent.includes('/*')) { return true; } break; case 'yaml': case 'yml': // YAML: # comments if (trimmedLine.startsWith('#')) { return true; } break; case 'ini': case 'properties': // INI/Properties: # and ; comments if (trimmedLine.startsWith('#') || trimmedLine.startsWith(';')) { return true; } break; } return false; } isInTestFile(filePath) { const testPatterns = [ /test/i, /spec/i, /mock/i, /stub/i, /fixture/i, /example/i, /sample/i, /demo/i ]; return testPatterns.some(pattern => pattern.test(filePath)); } isInDocumentation(filePath) { const docPatterns = [ /readme/i, /docs?/i, /documentation/i, /guide/i, /tutorial/i, /example/i, /sample/i ]; return docPatterns.some(pattern => pattern.test(filePath)); } isInDevelopment(filePath) { const devPatterns = [ /development/i, /dev/i, /staging/i, /localhost/i, /127\.0\.0\.1/i, /test/i, /debug/i ]; return devPatterns.some(pattern => pattern.test(filePath)); } isFalsePositive(lineContent) { const falsePositivePatterns = [ /example/i, /demo/i, /test/i, /mock/i, /sample/i, /placeholder/i, /your[_-]?data/i, /dummy/i, /fake/i, /development/i, /dev/i, /staging/i ]; return falsePositivePatterns.some(pattern => pattern.test(lineContent)); } // Validation methods: For error patterns! validateStackTraceExposure(text) { return text.toLowerCase().includes('stack') && (text.includes('error.stack') || text.includes('exception.stack') || text.includes('stacktrace') || text.includes('traceback')); } validateStackTraceResponse(text) { return text.toLowerCase().includes('stack') && text.includes('res.status') && text.includes('.send('); } validateDatabaseErrorExposure(text) { const dbErrorKeywords = ['sql_error', 'database_error', 'db_error', 'query_error']; return dbErrorKeywords.some(keyword => text.toLowerCase().includes(keyword)); } validateDatabaseSpecificError(text) { const dbKeywords = ['mysql', 'postgres', 'mongodb', 'sqlite']; return dbKeywords.some(db => text.toLowerCase().includes(db) && text.toLowerCase().includes('error')); } validateFileSystemErrorExposure(text) { const fsErrorKeywords = ['file_error', 'fs_error', 'path_error', 'directory_error']; return fsErrorKeywords.some(keyword => text.toLowerCase().includes(keyword)); } validateNetworkErrorExposure(text) { const networkErrorKeywords = ['network_error', 'http_error', 'request_error', 'response_error']; return networkErrorKeywords.some(keyword => text.toLowerCase().includes(keyword)); } validateDetailedErrorExposure(text) { return text.toLowerCase().includes('error.message') || text.toLowerCase().includes('exception.message') || text.toLowerCase().includes('error.details') || text.toLowerCase().includes('exception.details'); } validateErrorObjectLogging(text) { return text.toLowerCase().includes('error') || text.toLowerCase().includes('exception'); } validatePHPErrorLogging(text) { return text.toLowerCase().includes('error_log') || text.toLowerCase().includes('syslog') || text.toLowerCase().includes('trigger_error'); } validatePHPDebugOutput(text) { return text.toLowerCase().includes('print_r') || text.toLowerCase().includes('var_dump') || text.toLowerCase().includes('var_export'); } validatePythonErrorLogging(text) { return text.toLowerCase().includes('logging.') || text.toLowerCase().includes('logger.'); } validatePythonErrorPrinting(text) { return text.toLowerCase().includes('print') && (text.toLowerCase().includes('error') || text.toLowerCase().includes('exception')); } validateJavaErrorLogging(text) { return text.toLowerCase().includes('log.') || text.toLowerCase().includes('logger.'); } validateJavaErrorPrinting(text) { return text.toLowerCase().includes('system.out.println') && (text.toLowerCase().includes('error') || text.toLowerCase().includes('exception')); } validateRailsErrorLogging(text) { return text.toLowerCase().includes('rails.logger'); } validateSpringErrorLogging(text) { return text.toLowerCase().includes('logger.') && !text.toLowerCase().includes('rails.logger'); } validateDjangoErrorLogging(text) { return text.toLowerCase().includes('logging.') || text.toLowerCase().includes('logger.'); } validateDetailedErrorResponse(text) { return text.toLowerCase().includes('res.status') && text.toLowerCase().includes('.json(') && text.toLowerCase().includes('error'); } validateErrorResponseSending(text) { return text.toLowerCase().includes('res.send(') && (text.toLowerCase().includes('error') || text.toLowerCase().includes('exception')); } validateErrorTemplateRendering(text) { return text.toLowerCase().includes('render_template') || text.toLowerCase().includes('jsonify'); } generateSuggestion(issueType, context) { const framework = context.framework; switch (issueType) { case 'Stack trace logging': case 'Stack trace in HTTP response': if (framework === 'express') { return 'Never expose stack traces in production. Use error handling middleware and generic error messages. Consider using express-error-handler or similar libraries.'; } else if (framework === 'django') { return 'Set DEBUG=False in production settings. Use Django\'s built-in error handling and custom error templates.'; } else if (framework === 'rails') { return 'Configure Rails error handling in config/environments/production.rb. Use custom error pages and avoid exposing stack traces.'; } else if (framework === 'spring') { return 'Use Spring Boot\'s error handling with @ControllerAdvice. Configure custom error responses and avoid exposing stack traces.'; } return 'Never expose stack traces in production. Use generic error messages and proper error handling without information disclosure.'; case 'Database error logging': case 'Database-specific error logging': if (framework === 'express') { return 'Log database errors with sanitized messages. Use error codes instead of detailed error messages. Consider using database-specific error handling.'; } else if (framework === 'django') { return 'Use Django\'s database error handling. Log error codes instead of detailed messages. Configure database logging appropriately.'; } else if (framework === 'rails') { return 'Use Rails database error handling. Log error codes and sanitize database error messages. Configure database logging in production.'; } return 'Log database errors with sanitized messages. Use error codes instead of detailed error messages to prevent information disclosure.'; case 'File system error logging': return 'Log file system errors with generic messages. Avoid exposing file paths or system details in error messages.'; case 'Network error logging': return 'Log network errors with generic messages. Avoid exposing internal network details or sensitive information.'; case 'Detailed error message logging': return 'Use generic error messages instead of detailed ones. Implement proper error handling without exposing sensitive information.'; case 'Error object logging': return 'Avoid logging entire error objects. Extract only necessary information and use generic error messages.'; case 'PHP error logging': if (framework === 'laravel') { return 'Use Laravel\'s built-in error handling and logging. Configure error reporting appropriately in production.'; } return 'Use PHP\'s error handling functions with sanitized messages. Configure error reporting appropriately.'; case 'PHP debug output': return 'Remove debug output functions (print_r, var_dump, var_export) from production code. Use proper logging instead.'; case 'Python error logging': if (framework === 'django') { return 'Use Django\'s logging configuration. Set appropriate log levels and avoid exposing sensitive information.'; } else if (framework === 'flask') { return 'Use Flask\'s error handling and logging. Configure logging appropriately and avoid exposing sensitive information.'; } return 'Use Python\'s logging module with appropriate levels. Avoid exposing sensitive information in error messages.'; case 'Python error printing': return 'Replace print statements with proper logging. Use logging module with appropriate levels and sanitized messages.'; case 'Java error logging': if (framework === 'spring') { return 'Use Spring Boot\'s logging configuration. Set appropriate log levels and use structured logging.'; } return 'Use Java logging frameworks with appropriate levels. Avoid exposing sensitive information in error messages.'; case 'Java error printing': return 'Replace System.out.println with proper logging. Use logging frameworks with appropriate levels.'; case 'Rails error logging': return 'Use Rails logging configuration. Set appropriate log levels and avoid exposing sensitive information.'; case 'Spring error logging': return 'Use Spring Boot\'s logging configuration. Set appropriate log levels and use structured logging.'; case 'Django error logging': return 'Use Django\'s logging configuration. Set appropriate log levels and avoid exposing sensitive information.'; case 'Detailed error response': return 'Use generic error responses instead of detailed ones. Implement proper error handling without exposing sensitive information.'; case 'Error response sending': return 'Send generic error responses instead of detailed error information. Implement proper error handling.'; case 'Error template rendering': return 'Use generic error templates instead of exposing detailed error information. Implement proper error handling.'; default: return 'Avoid exposing sensitive information in error messages. Use generic error messages, sanitize error output, and implement proper error handling without information disclosure.'; } } } exports.InsecureErrorHandlingRule = InsecureErrorHandlingRule; //# sourceMappingURL=insecure-error-handling.js.map