UNPKG

bugnitor-security-scanner

Version:

AI-Era Security Scanner: Intelligent automated security review agent specializing in AI-generated vulnerability patterns

412 lines (406 loc) 17.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AIVulnerabilityDetector = exports.aiVulnerabilityPatterns = void 0; exports.aiVulnerabilityPatterns = [ { id: 'missing-auth-check-delete', name: 'Missing Authorization Check on DELETE Operations', category: 'Broken Access Control', description: 'DELETE operations without proper authorization verification', aiContext: 'AI generates database deletion logic but lacks application context about user roles and permissions', patterns: [ /(?:DELETE\s+FROM|\.delete\s*\(|\.remove\s*\(|\.destroy\s*\()(?![\s\S]{0,200}(?:auth|permission|role|isAdmin|canDelete|checkAuth|authorize|verify|middleware))/gi, /router\.(delete|del)\s*\([^)]*\)(?![\s\S]{0,200}(?:auth|permission|middleware|isAdmin|canDelete))/gi, /app\.delete\s*\([^)]*\)(?![\s\S]{0,200}(?:auth|permission|middleware|isAdmin|canDelete))/gi, /prisma\.\w+\.delete\s*\((?![\s\S]{0,100}(?:where.*userId|where.*ownerId|auth|permission))/gi ], contextPatterns: [ /delete|remove|destroy/gi ], excludePatterns: [ /test|spec|example|demo/gi ], severity: 'critical', confidence: 0.9, fileTypes: ['js', 'ts', 'jsx', 'tsx', 'py', 'php', 'java'], cwe: 'CWE-862', owasp: 'A01:2021 – Broken Access Control', impact: 'Unauthorized deletion of resources, data loss, privilege escalation', remediation: { description: 'Add proper authorization checks before DELETE operations', effort: 'medium', codeExample: `// Before (AI-generated): await prisma.resource.delete({ where: { id } }); // After (secure): if (!user.isAdmin && resource.ownerId !== user.id) { throw new Error('Unauthorized'); } await prisma.resource.delete({ where: { id } });` } }, { id: 'missing-auth-check-admin', name: 'Missing Authorization Check on Admin Routes', category: 'Broken Access Control', description: 'Admin endpoints without proper role verification', aiContext: 'AI creates admin functionality but doesnt implement role checking logic', patterns: [ /\/admin\/[^'"\s]*['"]?\s*,?\s*(?:async\s+)?\([^)]*\)\s*(?:=>|{)(?![\s\S]{0,300}(?:isAdmin|role.*admin|checkAdmin|requireAdmin|adminOnly))/gi, /app\.(get|post|put|delete)\s*\(\s*['"][^'"]*admin[^'"]*['"](?![\s\S]{0,200}(?:isAdmin|role.*admin|middleware.*admin))/gi, /router\.(get|post|put|delete)\s*\(\s*['"][^'"]*admin[^'"]*['"](?![\s\S]{0,200}(?:isAdmin|role.*admin|middleware.*admin))/gi ], severity: 'critical', confidence: 0.85, fileTypes: ['js', 'ts', 'jsx', 'tsx', 'py', 'php'], cwe: 'CWE-862', owasp: 'A01:2021 – Broken Access Control', impact: 'Complete administrative access bypass, system compromise', remediation: { description: 'Implement role-based access control for admin routes', effort: 'medium', codeExample: `// Add authorization middleware: app.post('/admin/users', requireAdmin, async (req, res) => { // Admin logic here });` } }, { id: 'direct-db-input', name: 'Direct Database Query with User Input', category: 'Injection Flaws', description: 'User input directly concatenated into database queries', aiContext: 'AI generates functional database queries but often uses string concatenation instead of parameterized queries', patterns: [ /(?:query|execute|prepare)\s*\(\s*["`'][^"`']*\$\{[^}]*\}[^"`']*["`']/gi, /(?:query|execute|prepare)\s*\(\s*["`'][^"`']*\+[^"`']*["`']/gi, /(?:SELECT|INSERT|UPDATE|DELETE)[^;]*\+\s*(?:req\.|request\.|params\.|body\.|query\.)/gi, /(?:SELECT|INSERT|UPDATE|DELETE)[^;]*\$\{[^}]*(?:req\.|request\.|params\.|body\.|query\.)/gi, /db\.query\s*\([^)]*\+[^)]*req\./gi ], contextPatterns: [ /query|sql|database|db/gi ], severity: 'critical', confidence: 0.95, fileTypes: ['js', 'ts', 'py', 'php', 'java', 'cs'], cwe: 'CWE-89', owasp: 'A03:2021 – Injection', impact: 'Complete database compromise, data theft, data manipulation', remediation: { description: 'Use parameterized queries or prepared statements', effort: 'medium', codeExample: `// Instead of: const query = \`SELECT * FROM users WHERE id = \${userId}\`; // Use: const query = 'SELECT * FROM users WHERE id = ?'; db.query(query, [userId]);` } }, { id: 'unsanitized-csv-processing', name: 'Unsanitized CSV Processing', category: 'Injection Flaws', description: 'CSV data processed without validation, leading to CSV injection', aiContext: 'AI generates CSV parsing logic focusing on functionality, not security validation', patterns: [ /parseCSV\s*\([^)]*\)(?![\s\S]{0,200}(?:sanitize|validate|escape|clean))/gi, /csv\.parse\s*\([^)]*\)(?![\s\S]{0,200}(?:sanitize|validate|escape))/gi, /\.split\s*\(\s*['"],['"]\s*\)(?![\s\S]{0,100}(?:sanitize|validate|escape))/gi, /Papa\.parse\s*\([^)]*\)(?![\s\S]{0,200}(?:sanitize|validate|transform))/gi ], contextPatterns: [ /csv|comma|separated|parse/gi ], severity: 'high', confidence: 0.8, fileTypes: ['js', 'ts', 'py', 'php'], cwe: 'CWE-1236', owasp: 'A03:2021 – Injection', impact: 'CSV injection, formula injection in spreadsheet applications', remediation: { description: 'Validate and sanitize CSV data before processing', effort: 'low', codeExample: `// Sanitize CSV cells to prevent formula injection const sanitizeCSVCell = (cell) => { if (typeof cell === 'string' && /^[=+@-]/.test(cell)) { return "'" + cell; // Prefix with single quote } return cell; };` } }, { id: 'hardcoded-secrets-examples', name: 'Hardcoded Secrets from AI Examples', category: 'Sensitive Data Exposure', description: 'API keys, tokens, or secrets hardcoded from AI-generated examples', aiContext: 'Developers include example secrets in AI prompts, and AI incorporates them into generated code', patterns: [ /(?:api[_-]?key|apikey|secret|token|password)\s*[:=]\s*["`'](?:sk_|pk_|test_|demo_|example_|your_|my_|sample_)[^"`']+["`']/gi, /(?:jwt[_-]?secret|signing[_-]?key)\s*[:=]\s*["`'](?:your|my|demo|test|example|secret)[^"`']*["`']/gi, /(?:database[_-]?url|db[_-]?url)\s*[:=]\s*["`'](?:mongodb|postgresql|mysql).*(?:localhost|example\.com|test\.db)[^"`']*["`']/gi, /process\.env\.\w+\s*\|\|\s*["`'][^"`']+["`']/gi // Fallback values that might be secrets ], contextPatterns: [ /key|secret|token|password|api/gi ], excludePatterns: [ /process\.env\.\w+/gi // Exclude when properly using env vars ], severity: 'critical', confidence: 0.9, fileTypes: ['js', 'ts', 'py', 'php', 'java', 'cs', 'go'], cwe: 'CWE-798', owasp: 'A02:2021 – Cryptographic Failures', impact: 'Complete account compromise, API abuse, unauthorized access', remediation: { description: 'Replace hardcoded secrets with environment variables', effort: 'low', codeExample: `// Instead of: const apiKey = "sk_live_example123456"; // Use: const apiKey = process.env.STRIPE_API_KEY; if (!apiKey) throw new Error('Missing API key');` } }, { id: 'detailed-error-exposure', name: 'Detailed Error Information Exposure', category: 'Sensitive Data Exposure', description: 'Detailed error messages exposed to users revealing internal information', aiContext: 'AI generates comprehensive error handling but exposes internal details for debugging', patterns: [ /console\.error\s*\([^)]*error(?:\.stack|\.message)?[^)]*\)/gi, /res\.(?:status|send|json)\s*\([^)]*error(?:\.stack|\.message|\.toString\(\))[^)]*\)/gi, /throw\s+new\s+Error\s*\([^)]*\$\{[^}]*error[^}]*\}/gi, /console\.log\s*\([^)]*error[^)]*\)/gi, /logger\.error\s*\([^)]*error\.stack[^)]*\)/gi ], contextPatterns: [ /error|catch|exception/gi ], excludePatterns: [ /development|dev|debug/gi ], severity: 'medium', confidence: 0.7, fileTypes: ['js', 'ts', 'py', 'php', 'java'], cwe: 'CWE-209', owasp: 'A09:2021 – Security Logging and Monitoring Failures', impact: 'Information leakage, system reconnaissance for attackers', remediation: { description: 'Log detailed errors server-side, return generic messages to users', effort: 'low', codeExample: `// Instead of: catch (error) { res.status(500).json({ error: error.message }); } // Use: catch (error) { logger.error('Operation failed:', error); res.status(500).json({ error: 'Internal server error' }); }` } }, { id: 'weak-crypto-ai-suggestion', name: 'Weak Cryptographic Algorithm from AI', category: 'Insecure Design', description: 'Use of weak cryptographic algorithms suggested by AI', aiContext: 'AI may suggest older cryptographic methods from its training data without considering current security standards', patterns: [ /crypto\.createHash\s*\(\s*["`'](?:md5|sha1)["`']\s*\)/gi, /hashlib\.(?:md5|sha1)\s*\(\s*\)/gi, /MessageDigest\.getInstance\s*\(\s*["`'](?:MD5|SHA-1|SHA1)["`']\s*\)/gi, /hash\s*\(\s*["`'](?:md5|sha1)["`']/gi, /\.digest\s*\(\s*["`'](?:md5|sha1)["`']\s*\)/gi ], contextPatterns: [ /hash|crypto|digest|password/gi ], excludePatterns: [ /etag|checksum|legacy|compatibility/gi // Exclude non-security uses ], severity: 'medium', confidence: 0.8, fileTypes: ['js', 'ts', 'py', 'java', 'cs', 'go'], cwe: 'CWE-327', owasp: 'A02:2021 – Cryptographic Failures', impact: 'Cryptographic vulnerabilities, hash collisions, data compromise', remediation: { description: 'Use strong, modern cryptographic algorithms', effort: 'low', codeExample: `// Instead of: crypto.createHash('md5').update(password).digest('hex'); // Use: bcrypt.hash(password, 12); // For passwords // or crypto.createHash('sha256').update(data).digest('hex'); // For data` } }, { id: 'unvalidated-redirect', name: 'Unvalidated Redirect from AI', category: 'Broken Access Control', description: 'Redirect functionality without URL validation', aiContext: 'AI generates redirect logic but doesnt include URL validation to prevent open redirects', patterns: [ /res\.redirect\s*\([^)]*req\.(?:query|body|params)\.[^)]*\)/gi, /response\.redirect\s*\([^)]*request\.[^)]*\)/gi, /window\.location\s*=\s*[^;]*req\./gi, /location\.href\s*=\s*[^;]*params\./gi ], contextPatterns: [ /redirect|location|href/gi ], severity: 'medium', confidence: 0.8, fileTypes: ['js', 'ts', 'py', 'php'], cwe: 'CWE-601', owasp: 'A01:2021 – Broken Access Control', impact: 'Phishing attacks, malicious redirects', remediation: { description: 'Validate redirect URLs against a whitelist', effort: 'low', codeExample: `// Validate redirect URL const allowedDomains = ['example.com', 'app.example.com']; const redirectUrl = new URL(req.query.redirect); if (!allowedDomains.includes(redirectUrl.hostname)) { throw new Error('Invalid redirect URL'); }` } }, { id: 'missing-input-validation', name: 'Missing Input Validation on AI-Generated Endpoints', category: 'Injection Flaws', description: 'API endpoints without proper input validation', aiContext: 'AI focuses on functional implementation but often skips input validation and sanitization', patterns: [ /app\.(post|put|patch)\s*\([^)]*\)\s*,?\s*(?:async\s+)?\([^)]*\)\s*(?:=>|{)(?![\s\S]{0,300}(?:validate|sanitize|check|joi\.|yup\.|zod\.))/gi, /router\.(post|put|patch)\s*\([^)]*\)\s*,?\s*(?:async\s+)?\([^)]*\)\s*(?:=>|{)(?![\s\S]{0,300}(?:validate|sanitize|check))/gi, /req\.body(?![\s\S]{0,100}(?:validate|sanitize|check|trim|escape))/gi, /request\.json\(\)(?![\s\S]{0,100}(?:validate|sanitize|parse|schema))/gi ], contextPatterns: [ /req\.body|request\.json|form|input/gi ], excludePatterns: [ /get|delete/gi // Exclude GET/DELETE methods ], severity: 'high', confidence: 0.75, fileTypes: ['js', 'ts', 'py', 'php'], cwe: 'CWE-20', owasp: 'A03:2021 – Injection', impact: 'Data corruption, injection attacks, application errors', remediation: { description: 'Add comprehensive input validation', effort: 'medium', codeExample: `// Add validation middleware const { body, validationResult } = require('express-validator'); app.post('/users', [ body('email').isEmail().normalizeEmail(), body('password').isLength({ min: 8 }), ], (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } // Process validated input });` } } ]; class AIVulnerabilityDetector { detectAIVulnerabilities(content, filename) { const fileExtension = filename.split('.').pop()?.toLowerCase(); if (!fileExtension) return []; const results = []; for (const pattern of exports.aiVulnerabilityPatterns) { if (!pattern.fileTypes.includes(fileExtension)) continue; const matches = []; for (const regex of pattern.patterns) { let match; while ((match = regex.exec(content)) !== null) { const context = this.getMatchContext(content, match.index || 0); const confidence = this.calculateConfidence(pattern, match, context, filename); // Higher threshold for AI-specific patterns if (confidence < 0.6) continue; matches.push({ match, confidence, context }); if (!regex.global) break; } regex.lastIndex = 0; } if (matches.length > 0) { results.push({ pattern, matches }); } } return results; } getMatchContext(content, index, contextSize = 200) { const start = Math.max(0, index - contextSize); const end = Math.min(content.length, index + contextSize); return content.substring(start, end); } calculateConfidence(pattern, match, context, filename) { let confidence = pattern.confidence; // File type adjustments if (filename.includes('test') || filename.includes('spec') || filename.includes('mock')) { confidence *= 0.5; } if (filename.includes('example') || filename.includes('demo') || filename.includes('sample')) { confidence *= 0.4; } // Route/API file boost if (filename.includes('route') || filename.includes('api') || filename.includes('endpoint')) { confidence *= 1.2; } // Context pattern matching if (pattern.contextPatterns) { let hasContext = false; for (const contextPattern of pattern.contextPatterns) { if (contextPattern.test(context)) { hasContext = true; confidence *= 1.15; break; } } if (!hasContext) { confidence *= 0.8; } } // Exclude pattern matching if (pattern.excludePatterns) { for (const excludePattern of pattern.excludePatterns) { if (excludePattern.test(match[0]) || excludePattern.test(context)) { confidence *= 0.4; break; } } } // AI-specific indicators const aiIndicators = [ /\/\/ generated by|auto-generated|ai-generated/gi, /\/\/ example|\/\/ todo|\/\/ fixme/gi, /copilot|chatgpt|claude|assistant/gi ]; for (const aiIndicator of aiIndicators) { if (aiIndicator.test(context)) { confidence *= 1.3; // Boost confidence for AI-generated code markers break; } } return Math.min(1.0, Math.max(0.0, confidence)); } } exports.AIVulnerabilityDetector = AIVulnerabilityDetector; //# sourceMappingURL=ai-vulnerability-detector.js.map