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
496 lines • 21.8 kB
JavaScript
;
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 with context-aware analysis';
this.severity = 'high';
this.aiCodePatterns = [
// AI generated code indicators: More specific assignment patterns!
// Medium severity
{
pattern: /(?:generated[_-]?by|ai[_-]?generated|copilot|chatgpt|gpt[_-]?generated|claude[_-]?generated)\s*[:=]\s*['"`]?[^'"`]*['"`]?/gi,
type: 'AI-Generated Code',
confidence: 0.7,
severity: 'medium',
validation: (text) => this.validateAiGeneratedCode(text)
},
// High severity
{
pattern: /(?:ai|generated|copilot)\s*[:=]\s*['"`]?[^'"`]*(?:unvalidated|unreviewed|unchecked)['"`]?/gi,
type: 'Unvalidated AI Code',
confidence: 0.85,
severity: 'high',
validation: (text) => this.validateUnvalidatedCode(text)
},
// High severity
{
pattern: /(?:ai|generated|copilot)\s*[:=]\s*['"`]?[^'"`]*(?:no[_-]?review|without[_-]?review|skip[_-]?review)['"`]?/gi,
type: 'AI Code Without Security Review',
confidence: 0.9,
severity: 'high',
validation: (text) => this.validateNoReviewCode(text)
},
// Critical severity
{
pattern: /(?:ai|generated|copilot)\s*[:=]\s*['"`]?[^'"`]*(?:vulnerable|insecure|unsafe)['"`]?/gi,
type: 'Vulnerable AI-Generated Code',
confidence: 0.95,
severity: 'critical',
validation: (text) => this.validateVulnerableCode(text)
},
// Critical severity
{
pattern: /(?:ai|generated|copilot)\s*[:=]\s*['"`]?[^'"`]*(?:bypass|skip|ignore)\s*[:=]\s*['"`]?[^'"`]*(?:security|validation)['"`]?/gi,
type: 'AI Code Bypassing Security',
confidence: 0.95,
severity: 'critical',
validation: (text) => this.validateSecurityBypass(text)
},
// Dangerous code patterns: eval, system commands, SQL injection
{
pattern: /eval\s*\(\s*['"`]?[^'"`]*\$\{[^}]+\}[^'"`]*['"`]?/gi,
type: 'AI-Generated Eval with Variables',
confidence: 0.9,
severity: 'critical',
validation: (text) => this.validateEvalWithVariables(text)
},
// Critical severity
{
pattern: /(?:exec|system|spawn)\s*\(\s*['"`]?[^'"`]*\$\{[^}]+\}[^'"`]*['"`]?/gi,
type: 'AI-Generated System Commands',
confidence: 0.9,
severity: 'critical',
validation: (text) => this.validateSystemCommands(text)
},
// High severity
{
pattern: /(?:query|sql)\s*[:=]\s*['"`]?[^'"`]*\$\{[^}]+\}[^'"`]*['"`]?/gi,
type: 'AI-Generated SQL with Variables',
confidence: 0.85,
severity: 'high',
validation: (text) => this.validateSqlWithVariables(text)
},
// Multi line AI injection patterns!
{
pattern: /(?:prompt|input)\s*[:=]\s*['"`]?[^'"`]*(?:ignore|forget|system|assistant|user)\s*[:=]\s*['"`]?[^'"`]*(?:previous|above|instructions)['"`]?/gis,
type: 'Multi-Line AI Injection',
confidence: 0.9,
severity: 'critical',
validation: (text) => this.validateMultiLineInjection(text)
},
// AI generated file operations!
{
pattern: /(?:readFile|writeFile|fs\.(?:read|write))\s*\(\s*['"`]?[^'"`]*\$\{[^}]+\}[^'"`]*['"`]?/gi,
type: 'AI-Generated File Operations',
confidence: 0.8,
severity: 'high',
validation: (text) => this.validateFileOperations(text)
},
// AI generated network requests!
{
pattern: /(?:fetch|axios|request)\s*\(\s*['"`]?[^'"`]*\$\{[^}]+\}[^'"`]*['"`]?/gi,
type: 'AI-Generated Network Requests',
confidence: 0.75,
severity: 'medium',
validation: (text) => this.validateNetworkRequests(text)
}
];
this.falsePositivePatterns = [
// Development and testing patterns:
/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,
// Documentation and examples:
/documentation/i,
/readme/i,
/docs/i,
/example[_-]?code/i,
/sample[_-]?code/i,
/demo[_-]?code/i,
/tutorial/i,
/guide/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,
// Commit logs and version control:
/commit/i,
/git/i,
/svn/i,
/version/i,
/changelog/i,
/history/i,
// License headers:
/license/i,
/copyright/i,
/mit/i,
/apache/i,
/gpl/i,
/bsd/i,
// Security related false positives (likely safe):
/validate/i,
/review/i,
/secure/i,
/safe/i,
/sanitize/i,
/escape/i,
/filter/i,
/protect/i,
/audit/i,
/scan/i
];
}
check(fileContent) {
const issues = [];
const language = this.detectLanguage(fileContent.path);
const framework = this.detectFramework(fileContent.content, language);
const hasSecurityMeasures = this.hasSecurityMeasures(fileContent.content);
for (const { pattern, type, confidence, severity, validation } of this.aiCodePatterns) {
let matches;
// Handles 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];
const context = this.analyzeContext(fileContent, line, column, language, framework, hasSecurityMeasures, issues.length);
// Skips if in safe context
if (this.isSafeContext(context)) {
continue;
}
// Validates the AI code issue
if (!validation(matchedText)) {
continue;
}
// Calculates final confidence and severity based on context
const finalConfidence = this.calculateConfidence(confidence, context);
const finalSeverity = this.calculateSeverity(severity, context);
if (finalConfidence >= 0.5) {
issues.push(this.createIssue(fileContent.path, line, column, lineContent, `${finalSeverity.toUpperCase()}: ${type} detected (confidence: ${Math.round(finalConfidence * 100)}%): ${this.getLineContext(lineContent, column)}`, this.generateSuggestion(type, context), finalSeverity));
}
}
}
return issues;
}
analyzeContext(fileContent, line, column, language, framework, hasSecurityMeasures, issueCount) {
const lines = fileContent.lines;
const currentLine = lines[line - 1] || '';
const surroundingLines = lines.slice(Math.max(0, line - 3), line + 2);
return {
isInComment: this.isInComment(currentLine, language),
isInString: this.isInString(currentLine, column),
isInTestFile: this.isInTestFile(fileContent.path),
isInDocumentation: this.isInDocumentation(fileContent.path),
isInDevelopment: this.isInDevelopment(surroundingLines),
isInCommitLog: this.isInCommitLog(surroundingLines),
isInLicenseHeader: this.isInLicenseHeader(surroundingLines),
surroundingCode: surroundingLines.join('\n'),
language,
framework,
hasSecurityMeasures: hasSecurityMeasures || false,
issueCount: issueCount || 0
};
}
isSafeContext(context) {
if (context.isInComment)
return true;
if (context.isInTestFile)
return true;
if (context.isInDocumentation)
return true;
if (context.isInDevelopment)
return true;
if (context.isInCommitLog)
return true;
if (context.isInLicenseHeader)
return true;
if (this.falsePositivePatterns.some(pattern => pattern.test(context.surroundingCode))) {
return true;
}
return false;
}
detectLanguage(filePath) {
const ext = filePath.split('.').pop()?.toLowerCase();
const languageMap = {
'js': 'javascript',
'jsx': 'javascript',
'ts': 'typescript',
'tsx': 'typescript',
'py': 'python',
'php': 'php',
'rb': 'ruby',
'go': 'go',
'java': 'java',
'cs': 'csharp'
};
return languageMap[ext || ''] || 'unknown';
}
detectFramework(content, language) {
if (language === 'javascript' || language === 'typescript') {
if (content.includes('react') || content.includes('React'))
return 'react';
if (content.includes('vue') || content.includes('Vue'))
return 'vue';
if (content.includes('angular') || content.includes('Angular'))
return 'angular';
if (content.includes('express') || content.includes('Express'))
return 'express';
}
if (language === 'python') {
if (content.includes('django') || content.includes('Django'))
return 'django';
if (content.includes('flask') || content.includes('Flask'))
return 'flask';
if (content.includes('fastapi') || content.includes('FastAPI'))
return 'fastapi';
}
return undefined;
}
isInComment(line, language) {
const trimmed = line.trim();
if (language === 'javascript' || language === 'typescript') {
return trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*');
}
if (language === 'python') {
return trimmed.startsWith('#');
}
if (language === 'php') {
return trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('#');
}
return false;
}
isInString(line, column) {
const before = line.substring(0, column);
const quotes = (before.match(/['"`]/g) || []).length;
return quotes % 2 === 1;
}
isInTestFile(filePath) {
return filePath.includes('test') ||
filePath.includes('spec') ||
filePath.includes('__tests__') ||
filePath.match(/\.(test|spec)\./i) !== null;
}
isInDocumentation(filePath) {
const docPatterns = [
/docs?\//i,
/documentation/i,
/examples?/i,
/samples?/i,
/tutorials?/i,
/guides?/i,
/readme/i,
/\.md$/i,
/\.rst$/i,
/\.txt$/i
];
return docPatterns.some(pattern => pattern.test(filePath));
}
isInDevelopment(lines) {
return lines.some(line => line.includes('development') ||
line.includes('dev') ||
line.includes('staging') ||
line.includes('localhost') ||
line.includes('127.0.0.1') ||
line.includes('NODE_ENV') ||
line.includes('DEBUG'));
}
isInCommitLog(lines) {
return lines.some(line => line.includes('commit') ||
line.includes('git') ||
line.includes('svn') ||
line.includes('version') ||
line.includes('changelog') ||
line.includes('history'));
}
isInLicenseHeader(lines) {
return lines.some(line => line.includes('license') ||
line.includes('copyright') ||
line.includes('MIT') ||
line.includes('Apache') ||
line.includes('GPL') ||
line.includes('BSD'));
}
hasSecurityMeasures(content) {
const securityPatterns = [
/validate/i,
/review/i,
/secure/i,
/safe/i,
/sanitize/i,
/escape/i,
/filter/i,
/protect/i,
/audit/i,
/scan/i
];
return securityPatterns.some(pattern => pattern.test(content));
}
calculateConfidence(baseConfidence, context) {
let confidence = baseConfidence;
// Adjusts confidence based on context
if (context.hasSecurityMeasures)
confidence *= 0.7; // Reduces if security measures present
if (context.framework)
confidence *= 1.1; // Increases for known frameworks
return Math.min(confidence, 1.0);
}
calculateSeverity(baseSeverity, context) {
let severity = baseSeverity;
// Auto escalates severity if multiple issues found
if (context.issueCount > 2) {
if (severity === 'medium')
severity = 'high';
if (severity === 'high')
severity = 'critical';
}
// Reduces severity in development context
if (context.isInDevelopment) {
if (severity === 'critical')
severity = 'high';
if (severity === 'high')
severity = 'medium';
}
return severity;
}
// Validation methods for different AI code issues!
validateAiGeneratedCode(text) {
const aiKeywords = ['generated', 'ai', 'copilot', 'chatgpt', 'gpt', 'claude'];
return aiKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateUnvalidatedCode(text) {
const unvalidatedKeywords = ['unvalidated', 'unreviewed', 'unchecked'];
return unvalidatedKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateNoReviewCode(text) {
const noReviewKeywords = ['no[_-]?review', 'without[_-]?review', 'skip[_-]?review'];
return noReviewKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateVulnerableCode(text) {
const vulnerableKeywords = ['vulnerable', 'insecure', 'unsafe'];
return vulnerableKeywords.some(keyword => text.toLowerCase().includes(keyword));
}
validateSecurityBypass(text) {
const bypassKeywords = ['bypass', 'skip', 'ignore'];
const securityKeywords = ['security', 'validation'];
return bypassKeywords.some(bypass => text.toLowerCase().includes(bypass)) &&
securityKeywords.some(security => text.toLowerCase().includes(security));
}
validateEvalWithVariables(text) {
return text.includes('eval') && text.includes('${');
}
validateSystemCommands(text) {
const systemKeywords = ['exec', 'system', 'spawn'];
return systemKeywords.some(keyword => text.toLowerCase().includes(keyword)) && text.includes('${');
}
validateSqlWithVariables(text) {
const sqlKeywords = ['query', 'sql'];
return sqlKeywords.some(keyword => text.toLowerCase().includes(keyword)) && text.includes('${');
}
validateMultiLineInjection(text) {
const injectionKeywords = ['ignore', 'forget', 'system', 'assistant', 'user'];
const contextKeywords = ['previous', 'above', 'instructions'];
return injectionKeywords.some(injection => text.toLowerCase().includes(injection)) &&
contextKeywords.some(context => text.toLowerCase().includes(context));
}
validateFileOperations(text) {
const fileKeywords = ['readFile', 'writeFile', 'fs.read', 'fs.write'];
return fileKeywords.some(keyword => text.toLowerCase().includes(keyword)) && text.includes('${');
}
validateNetworkRequests(text) {
const networkKeywords = ['fetch', 'axios', 'request'];
return networkKeywords.some(keyword => text.toLowerCase().includes(keyword)) && text.includes('${');
}
getLineContext(lineContent, column) {
const start = Math.max(0, column - 20);
const end = Math.min(lineContent.length, column + 20);
return lineContent.substring(start, end).trim();
}
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) {
// Finds 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;
// Gets 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;
}
generateSuggestion(type, context) {
const suggestions = {
'AI-Generated Code': 'Implement mandatory code review for all AI-generated code. Use automated security scanning tools.',
'Unvalidated AI Code': 'Establish validation processes for AI-generated code. Implement automated testing and security checks.',
'AI Code Without Security Review': 'Require security review for all AI-generated code before deployment. Use static analysis tools.',
'Vulnerable AI-Generated Code': 'Immediately review and fix vulnerabilities in AI-generated code. Implement secure coding practices.',
'AI Code Bypassing Security': 'Remove security bypasses from AI-generated code. Implement proper security controls and validation.',
'AI-Generated Eval with Variables': 'Replace eval() with safer alternatives. Use JSON.parse() or structured data handling.',
'AI-Generated System Commands': 'Avoid system commands with user input. Use parameterized commands or built-in APIs.',
'AI-Generated SQL with Variables': 'Use parameterized queries or ORM. Never concatenate user input into SQL strings.',
'Multi-Line AI Injection': 'Implement input validation and sanitization. Use content filtering for AI prompts.',
'AI-Generated File Operations': 'Validate file paths and implement access controls. Use safe file handling libraries.',
'AI-Generated Network Requests': 'Validate URLs and implement request sanitization. Use secure HTTP libraries.'
};
let suggestion = suggestions[type] || 'Implement comprehensive security review for AI-generated code. Use automated scanning and manual validation.';
if (context.framework) {
suggestion += ` For ${context.framework}, consider using framework-specific security features and validation patterns.`;
if (context.framework === 'react') {
suggestion += ' Use React security best practices and avoid dangerous patterns like eval().';
}
else if (context.framework === 'django') {
suggestion += ' Use Django security features and avoid raw SQL queries.';
}
else if (context.framework === 'express') {
suggestion += ' Use Express security middleware and input validation.';
}
}
if (context.issueCount > 2) {
suggestion += ' Multiple AI-generated code issues detected. Consider implementing a comprehensive AI code review process.';
}
return suggestion;
}
}
exports.AiGeneratedCodeValidationRule = AiGeneratedCodeValidationRule;
//# sourceMappingURL=ai-generated-code-validation.js.map