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

225 lines 9.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AiGeneratedCodeValidationRule = void 0; const types_1 = require("../types"); class AiGeneratedCodeValidationRule extends types_1.BaseRule { constructor() { super(...arguments); this.name = 'ai-generated-code-validation'; this.description = 'Detects security issues in AI-generated code and validates its safety'; this.severity = 'high'; this.aiCodePatterns = [ { pattern: /(?:generated[_-]?by|ai[_-]?generated|copilot|chatgpt|gpt[_-]?generated|claude[_-]?generated)/gi, type: 'AI-Generated Code', severity: 'medium' }, { pattern: /(?:ai|generated|copilot).*?(?:unvalidated|unreviewed|unchecked)/gi, type: 'Unvalidated AI Code', severity: 'high' }, { pattern: /(?:ai|generated|copilot).*?(?:no[_-]?review|without[_-]?review|skip[_-]?review)/gi, type: 'AI Code Without Security Review', severity: 'high' }, { pattern: /(?:ai|generated|copilot).*?(?:vulnerable|insecure|unsafe)/gi, type: 'Vulnerable AI-Generated Code', severity: 'critical' }, { pattern: /(?:ai|generated|copilot).*?(?:bypass|skip|ignore).*?(?:security|validation)/gi, type: 'AI Code Bypassing Security', severity: 'critical' }, { pattern: /(?:prompt|input).*?(?:ignore|forget|system|assistant|user).*?(?:previous|above|instructions)/gis, type: 'Multi-Line AI Injection', severity: 'critical' } ]; this.falsePositivePatterns = [ // Basic false positives /example/i, /demo/i, /test/i, /mock/i, /sample/i, /placeholder/i, /comment/i, /todo/i, /fixme/i, /\/\/.*/i, /#.*/i, /\/\*.*\*\//i, /<!--.*-->/i, /development/i, /dev/i, /staging/i, /localhost/i, // Security-related false positives /validate/i, /review/i, /secure/i, /safe/i, /sanitize/i, /escape/i, /filter/i, /protect/i, // Documentation and examples /documentation/i, /readme/i, /docs/i, /example[_-]?code/i, /sample[_-]?code/i, /demo[_-]?code/i, // Test files and directories /test[_-]?files?/i, /test[_-]?data/i, /test[_-]?cases/i, /spec[_-]?files?/i, /__tests__/i, /\.test\./i, /\.spec\./i, // Configuration and setup /config[_-]?example/i, /setup[_-]?example/i, /template[_-]?example/i, // Comments indicating safe usage /\/\/.*(?:safe|secure|validated|reviewed)/i, /#.*(?:safe|secure|validated|reviewed)/i, /\/\*.*(?:safe|secure|validated|reviewed).*\*\//i ]; this.contextPatterns = [ // Development environment indicators /NODE_ENV\s*[:=]\s*['"`]development['"`]/i, /process\.env\.NODE_ENV\s*[:=]\s*['"`]development['"`]/i, /DEBUG\s*[:=]\s*['"`]true['"`]/i, /debug\s*[:=]\s*true/i, // Test environment indicators /NODE_ENV\s*[:=]\s*['"`]test['"`]/i, /process\.env\.NODE_ENV\s*[:=]\s*['"`]test['"`]/i, /TESTING\s*[:=]\s*['"`]true['"`]/i, /testing\s*[:=]\s*true/i, // Local development indicators /localhost/i, /127\.0\.0\.1/i, /0\.0\.0\.0/i, /dev\./i, /staging\./i, /test\./i ]; } check(fileContent) { const issues = []; const isDevelopmentContext = this.isDevelopmentContext(fileContent.content); const isTestFile = this.isTestFile(fileContent.path); for (const { pattern, type, severity } of this.aiCodePatterns) { let matches; // Handle multi line patterns differently if (pattern.flags.includes('s')) { matches = this.findMultiLineMatches(fileContent.content, pattern); } else { matches = this.findMatches(fileContent.content, pattern); } for (const { match, line, column, lineContent } of matches) { const matchedText = match[0]; // Enhanced false positive detection if (this.isFalsePositive(lineContent, matchedText, fileContent.path)) { continue; } // Context-aware severity adjustment let adjustedSeverity = severity; if (isDevelopmentContext || isTestFile) { adjustedSeverity = this.adjustSeverityForContext(severity); } if (adjustedSeverity === 'medium' && isDevelopmentContext) { continue; } issues.push(this.createIssue(fileContent.path, line, column, lineContent, `${adjustedSeverity.charAt(0).toUpperCase() + adjustedSeverity.slice(1)}: ${type} detected`, this.getSuggestion(type, isDevelopmentContext, isTestFile), adjustedSeverity)); } } return issues; } isFalsePositive(lineContent, matchedText, filePath) { if (this.falsePositivePatterns.some(pattern => pattern.test(lineContent))) { return true; } if (filePath.match(/\.(md|txt|rst|adoc)$/i)) { return true; } if (filePath.match(/\.(example|sample|template)\./i)) { return true; } if (lineContent.trim().startsWith('//') || lineContent.trim().startsWith('#') || lineContent.trim().startsWith('/*') || lineContent.trim().startsWith('<!--')) { return true; } // Check for variable assignments that are clearly examples if (matchedText.match(/['"`](example|demo|test|sample|placeholder)['"`]/i) !== null) { return true; } return false; } isDevelopmentContext(content) { return this.contextPatterns.some(pattern => pattern.test(content)); } isTestFile(filePath) { return filePath.includes('test') || filePath.includes('spec') || filePath.includes('__tests__') || filePath.match(/\.(test|spec)\./i) !== null; } adjustSeverityForContext(originalSeverity) { switch (originalSeverity) { case 'critical': return 'high'; case 'high': return 'medium'; case 'medium': return 'medium'; // Keep medium as minimum default: return originalSeverity; } } findMultiLineMatches(content, pattern) { const matches = []; let match; const globalPattern = new RegExp(pattern.source, pattern.flags.includes('g') ? pattern.flags : pattern.flags + 'g'); while ((match = globalPattern.exec(content)) !== null) { // Find the line number for the match const matchIndex = match.index ?? 0; const beforeMatch = content.substring(0, matchIndex); const lineNumber = beforeMatch.split('\n').length; const lineStart = beforeMatch.lastIndexOf('\n') + 1; const columnNumber = matchIndex - lineStart + 1; // Get the line content (first line of multi-line match) const lines = content.split('\n'); const lineContent = lines[lineNumber - 1] || ''; matches.push({ match, line: lineNumber, column: columnNumber, lineContent }); if (!pattern.flags.includes('g')) break; } return matches; } getSuggestion(_type, isDevelopment, isTestFile) { const baseSuggestion = `Always validate and review AI-generated code for security vulnerabilities. Implement automated security scanning and manual code review processes.`; if (isDevelopment) { return `${baseSuggestion} Consider using a separate security review process for production deployments.`; } if (isTestFile) { return `${baseSuggestion} Ensure test files don't contain production security bypasses.`; } return baseSuggestion; } } exports.AiGeneratedCodeValidationRule = AiGeneratedCodeValidationRule; //# sourceMappingURL=ai-generated-code-validation.js.map