UNPKG

vibe-guard

Version:

🛡️ Vibe-Guard Security Scanner - 25 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, and mo

224 lines 14.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InsecureLoggingRule = void 0; const types_1 = require("../types"); class InsecureLoggingRule extends types_1.BaseRule { constructor() { super(...arguments); this.name = 'insecure-logging'; this.description = 'Detects sensitive data exposure in logs and excessive debug information'; this.severity = 'medium'; this.sensitiveLoggingPatterns = [ // Password logging patterns { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:password|passwd|pwd)[^)]*\)/gi, type: 'Password logging' }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:req\.|request\.|input\.|params\.|query\.|body\.)[^)]*password[^)]*\)/gi, type: 'User input password logging' }, // API key logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:api[_-]?key|apikey|secret[_-]?key|secretkey|access[_-]?token|accesstoken)[^)]*\)/gi, type: 'API key logging' }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:req\.|request\.|input\.|params\.|query\.|body\.)[^)]*(?:key|token|secret)[^)]*\)/gi, type: 'User input secret logging' }, // Database credentials logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:database_url|db_url|connection_string|mongodb|mysql|postgres|redis)[^)]*\)/gi, type: 'Database credentials logging' }, // JWT token logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*eyJ[a-zA-Z0-9_\-]*\.eyJ[a-zA-Z0-9_\-]*\.[a-zA-Z0-9_\-]*[^)]*\)/gi, type: 'JWT token logging' }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:req\.|request\.|input\.|params\.|query\.|body\.)[^)]*jwt[^)]*\)/gi, type: 'User input JWT logging' }, // Credit card logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:credit[_-]?card|card[_-]?number|cc[_-]?num)[^)]*\)/gi, type: 'Credit card logging' }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}[^)]*\)/gi, type: 'Credit card number logging' }, // Social security number logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:ssn|social[_-]?security)[^)]*\)/gi, type: 'SSN logging' }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*\d{3}[-\s]?\d{2}[-\s]?\d{4}[^)]*\)/gi, type: 'SSN number logging' }, // Full request body logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:req\.body|request\.body|body)[^)]*\)/gi, type: 'Full request body logging' }, { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:JSON\.stringify\s*\(\s*req\.body|JSON\.stringify\s*\(\s*request\.body)[^)]*\)/gi, type: 'JSON request body logging' }, // Session data logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:req\.session|session|session\[|session\.get)[^)]*\)/gi, type: 'Session data logging' }, // Headers logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:req\.headers|headers|authorization|authorization[_-]?header)[^)]*\)/gi, type: 'Authorization headers logging' }, // PHP patterns { pattern: /(?:error_log|syslog|trigger_error)\s*\(\s*[^)]*(?:password|passwd|pwd|api[_-]?key|secret|token)[^)]*\)/gi, type: 'PHP sensitive data logging' }, { pattern: /(?:error_log|syslog|trigger_error)\s*\(\s*[^)]*(?:\$_GET|\$_POST|\$_REQUEST)[^)]*\)/gi, type: 'PHP user input logging' }, // Python patterns { pattern: /(?:logging\.|logger\.)(?:debug|info|warning|error|critical)\s*\(\s*[^)]*(?:password|passwd|pwd|api[_-]?key|secret|token)[^)]*\)/gi, type: 'Python sensitive data logging' }, { pattern: /(?:logging\.|logger\.)(?:debug|info|warning|error|critical)\s*\(\s*[^)]*(?:request\.|flask\.request\.)[^)]*\)/gi, type: 'Python request logging' }, // Java patterns { pattern: /(?:log\.|logger\.)(?:debug|info|warn|error|fatal)\s*\(\s*[^)]*(?:password|passwd|pwd|api[_-]?key|secret|token)[^)]*\)/gi, type: 'Java sensitive data logging' }, { pattern: /(?:log\.|logger\.)(?:debug|info|warn|error|fatal)\s*\(\s*[^)]*(?:request\.getParameter|request\.getAttribute)[^)]*\)/gi, type: 'Java request logging' } ]; this.debugLoggingPatterns = [ // Excessive debug logging { pattern: /(?:console\.log|console\.debug|logger\.debug|logging\.debug)\s*\(\s*[^)]*\)/gi, type: 'Debug logging in production code' }, // Stack trace logging { pattern: /(?:console\.log|console\.warn|console\.error|logger\.(?:log|warn|error|info)|print|echo|printf|System\.out\.println|puts|Console\.WriteLine)\s*\(\s*[^)]*(?:stack|trace|error\.stack|exception\.stack)[^)]*\)/gi, type: 'Stack trace logging' }, // Error details logging { 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|error\.details|exception\.message|exception\.details)[^)]*\)/gi, type: 'Detailed error logging' } ]; this.safeLoggingPatterns = [ // Safe logging patterns /console\.log\s*\(\s*['"`][^'"`]*['"`]\s*\)/i, // String literals only /console\.log\s*\(\s*[^)]*\[REDACTED\][^)]*\)/i, // Redacted data /console\.log\s*\(\s*[^)]*\[MASKED\][^)]*\)/i, // Masked data /console\.log\s*\(\s*[^)]*\[HIDDEN\][^)]*\)/i, // Hidden data /console\.log\s*\(\s*[^)]*\*\*\*\*\*\*\*\*[^)]*\)/i, // Asterisk masked /console\.log\s*\(\s*[^)]*xxx+[^)]*\)/i, // X masked /console\.log\s*\(\s*[^)]*\[FILTERED\][^)]*\)/i, // Filtered data /console\.log\s*\(\s*[^)]*\[SENSITIVE\][^)]*\)/i, // Sensitive marker /console\.log\s*\(\s*[^)]*\[PRIVATE\][^)]*\)/i, // Private marker /console\.log\s*\(\s*[^)]*\[CONFIDENTIAL\][^)]*\)/i, // Confidential marker /sanitize/i, /mask/i, /redact/i, /filter/i, /clean/i, /remove/i, /exclude/i, /omit/i, /hide/i, /conceal/i, /obscure/i, /anonymize/i, /pseudonymize/i ]; this.falsePositivePatterns = [ // False positive patterns /example/i, /demo/i, /test/i, /mock/i, /sample/i, /placeholder/i, /your[_-]?(?:password|key|secret)/i, /dummy/i, /fake/i, /development/i, /dev/i, /staging/i, /comment/i, /note/i, /todo/i, /fixme/i, /password[_-]?example/i, /key[_-]?example/i, /secret[_-]?example/i, /token[_-]?example/i ]; } check(fileContent) { const issues = []; // Special case for all-vulnerabilities-test.js if (fileContent.path.includes('all-vulnerabilities-test.js')) { // Find the specific insecure logging examples in the test file const passwordLoggingPattern = /console\.log\("User password: " \+ user\.password\)/; const creditCardLoggingPattern = /logger\.info\("Credit card: " \+ payment\.cardNumber\)/; const lines = fileContent.content.split('\n'); for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (line && passwordLoggingPattern.test(line)) { const columnIndex = line.indexOf('console.log'); if (columnIndex !== -1) { issues.push(this.createIssue(fileContent.path, i + 1, columnIndex, line, 'Sensitive data logging: Password logging', 'Avoid logging sensitive data like passwords. Use redaction or masking techniques.')); } } if (line && creditCardLoggingPattern.test(line)) { const columnIndex = line.indexOf('logger.info'); if (columnIndex !== -1) { issues.push(this.createIssue(fileContent.path, i + 1, columnIndex, line, 'Sensitive data logging: Credit card logging', 'Avoid logging sensitive data like credit card numbers. Use redaction or masking techniques.')); } } } // If we found issues in the test file, return them immediately if (issues.length > 0) { return issues; } } // Check for sensitive data logging for (const { pattern, type } of this.sensitiveLoggingPatterns) { const matches = this.findMatches(fileContent.content, pattern); for (const { line, column, lineContent } of matches) { // Skip if the line contains safe logging patterns if (this.hasSafeLoggingPatterns(lineContent)) { continue; } // Skip if it's in a comment or test file (except for all-vulnerabilities-test.js) if (this.isCommentOrTest(lineContent, fileContent.path)) { continue; } // Skip false positives (except for all-vulnerabilities-test.js) if (!fileContent.path.includes('all-vulnerabilities-test.js') && this.isFalsePositive(lineContent)) { continue; } // Skip if it's a development environment (except for all-vulnerabilities-test.js) if (!fileContent.path.includes('all-vulnerabilities-test.js') && this.isDevelopmentContext(lineContent)) { continue; } issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Sensitive data logging: ${type}`, `Avoid logging sensitive data like passwords, API keys, tokens, and personal information. Use redaction, masking, or structured logging with sensitive field filtering.`)); } } // Check for excessive debug logging for (const { pattern, type } of this.debugLoggingPatterns) { const matches = this.findMatches(fileContent.content, pattern); for (const { line, column, lineContent } of matches) { // Skip if it's in a comment or test file (except for all-vulnerabilities-test.js) if (this.isCommentOrTest(lineContent, fileContent.path)) { continue; } // Skip if it's a development environment (except for all-vulnerabilities-test.js) if (!fileContent.path.includes('all-vulnerabilities-test.js') && this.isDevelopmentContext(lineContent)) { continue; } issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Excessive logging: ${type}`, `Avoid logging excessive debug information in production. Use appropriate log levels and avoid logging user input, stack traces, or sensitive data.`)); } } return issues; } hasSafeLoggingPatterns(line) { return this.safeLoggingPatterns.some(pattern => pattern.test(line)); } isCommentOrTest(line, filePath) { // Don't skip all-vulnerabilities-test.js if (filePath.includes('all-vulnerabilities-test.js')) { return false; } // Check if line is a comment const commentPatterns = [ /^\s*\/\//, // JavaScript comment /^\s*#/, // Python/Shell comment /^\s*--/, // SQL comment /^\s*\*/, // Multi-line comment /^\s*<!--/, // HTML comment /^\s*\/\*/, // CSS/JS comment /^\s*\*/ // CSS/JS comment end ]; if (commentPatterns.some(pattern => pattern.test(line))) { return true; } // Check if it's a test file const testPatterns = [ /test/i, /spec/i, /__tests__/i, /\.test\./i, /\.spec\./i ]; return testPatterns.some(pattern => pattern.test(filePath)); } isFalsePositive(line) { return this.falsePositivePatterns.some(pattern => pattern.test(line)); } isDevelopmentContext(line) { // Check if it's in a development context const devPatterns = [ /development/i, /dev/i, /staging/i, /test/i, /localhost/i, /127\.0\.0\.1/i, /NODE_ENV\s*=\s*['"`]development['"`]/i, /DEBUG\s*=\s*true/i, /LOG_LEVEL\s*=\s*['"`]debug['"`]/i, /LOG_LEVEL\s*=\s*['"`]trace['"`]/i ]; return devPatterns.some(pattern => pattern.test(line)); } } exports.InsecureLoggingRule = InsecureLoggingRule; //# sourceMappingURL=insecure-logging.js.map