UNPKG

codecrucible-synth

Version:

Production-Ready AI Development Platform with Multi-Voice Synthesis, Smithery MCP Integration, Enterprise Security, and Zero-Timeout Reliability

629 lines (558 loc) 18.2 kB
/** * Advanced Security Validator (ENHANCED) * Comprehensive security validation system for CodeCrucible Synth * Enhanced with 2024 AI security research and multi-agent red teaming * * Research findings integrated: * - 29.5% Python and 24.2% JavaScript code snippets contain vulnerabilities * - AI-specific prompt injection patterns and countermeasures * - Secret leak detection in AI-generated code */ import { Logger } from '../logger.js'; import * as crypto from 'crypto'; export interface SecurityPolicy { allowedCommands: string[]; blockedPatterns: RegExp[]; maxInputLength: number; allowCodeExecution: boolean; allowFileAccess: boolean; allowNetworkAccess: boolean; requireSandbox: boolean; } export interface ValidationResult { isValid: boolean; riskLevel: 'low' | 'medium' | 'high' | 'critical'; violations: SecurityViolation[]; sanitizedInput?: string; recommendations: string[]; } export interface SecurityViolation { type: | 'command_injection' | 'path_traversal' | 'malicious_pattern' | 'excessive_length' | 'suspicious_content'; description: string; severity: 'low' | 'medium' | 'high' | 'critical'; location?: string; pattern?: string; } export class AdvancedSecurityValidator { private logger: Logger; private policy: SecurityPolicy; private knownMaliciousPatterns!: RegExp[]; private suspiciousKeywords!: string[]; constructor(policy?: Partial<SecurityPolicy>) { this.logger = new Logger('AdvancedSecurityValidator'); this.policy = this.mergeWithDefaultPolicy(policy || {}); this.initializeMaliciousPatterns(); this.initializeSuspiciousKeywords(); } /** * Comprehensive input validation */ async validateInput(input: string, context?: string): Promise<ValidationResult> { const violations: SecurityViolation[] = []; let riskLevel: ValidationResult['riskLevel'] = 'low'; const recommendations: string[] = []; // Length validation if (input.length > this.policy.maxInputLength) { violations.push({ type: 'excessive_length', description: `Input exceeds maximum length of ${this.policy.maxInputLength} characters`, severity: 'medium', }); riskLevel = 'medium'; } // Command injection detection const commandViolations = this.detectCommandInjection(input); violations.push(...commandViolations); if (commandViolations.some(v => v.severity === 'critical')) { riskLevel = 'critical'; } // Path traversal detection const pathViolations = this.detectPathTraversal(input); violations.push(...pathViolations); if (pathViolations.some(v => v.severity === 'high')) { riskLevel = 'high'; } // Malicious pattern detection const patternViolations = this.detectMaliciousPatterns(input); violations.push(...patternViolations); if (patternViolations.some(v => v.severity === 'critical')) { riskLevel = 'critical'; } // Suspicious content analysis const contentViolations = await this.analyzeSuspiciousContent(input); violations.push(...contentViolations); // Update risk level based on all violations const highestSeverity = this.getHighestSeverity(violations); if (highestSeverity === 'critical') riskLevel = 'critical'; else if (highestSeverity === 'high' && riskLevel !== 'critical') riskLevel = 'high'; else if (highestSeverity === 'medium' && riskLevel === 'low') riskLevel = 'medium'; // Generate recommendations recommendations.push(...this.generateRecommendations(violations, riskLevel)); // Sanitize input if possible const sanitizedInput = violations.length === 0 ? input : this.sanitizeInput(input, violations); return { isValid: riskLevel !== 'critical' && violations.filter(v => v.severity === 'critical').length === 0, riskLevel, violations, sanitizedInput, recommendations, }; } /** * Detect command injection attempts */ private detectCommandInjection(input: string): SecurityViolation[] { const violations: SecurityViolation[] = []; // Shell metacharacters and patterns const commandPatterns = [ { pattern: /[;&|`$(){}]/g, severity: 'high' as const, desc: 'Shell metacharacters detected' }, { pattern: /\|\s*[a-z]/gi, severity: 'critical' as const, desc: 'Pipe to command detected' }, { pattern: /&&\s*[a-z]/gi, severity: 'critical' as const, desc: 'Command chaining detected' }, { pattern: /;\s*[a-z]/gi, severity: 'critical' as const, desc: 'Command separator detected' }, { pattern: /`[^`]+`/g, severity: 'critical' as const, desc: 'Command substitution detected' }, { pattern: /\$\([^)]+\)/g, severity: 'critical' as const, desc: 'Command substitution detected', }, { pattern: /rm\s+-r?f?\s+/gi, severity: 'critical' as const, desc: 'Dangerous delete command detected', }, { pattern: /curl\s+.*(\||>)/gi, severity: 'high' as const, desc: 'Network download with redirection', }, { pattern: /wget\s+.*(\||>)/gi, severity: 'high' as const, desc: 'Network download with redirection', }, { pattern: /chmod\s+[0-9]+/gi, severity: 'medium' as const, desc: 'File permission modification', }, { pattern: /sudo\s+/gi, severity: 'high' as const, desc: 'Privilege escalation attempt' }, { pattern: /su\s+/gi, severity: 'high' as const, desc: 'User switching attempt' }, ]; for (const { pattern, severity, desc } of commandPatterns) { const matches = input.match(pattern); if (matches) { violations.push({ type: 'command_injection', description: desc, severity, pattern: pattern.toString(), }); } } return violations; } /** * Detect path traversal attempts */ private detectPathTraversal(input: string): SecurityViolation[] { const violations: SecurityViolation[] = []; const pathPatterns = [ { pattern: /\.\.\/+/g, severity: 'high' as const, desc: 'Directory traversal detected' }, { pattern: /\.\.\\+/g, severity: 'high' as const, desc: 'Windows directory traversal detected', }, { pattern: /\/etc\/passwd/gi, severity: 'critical' as const, desc: 'System file access attempt', }, { pattern: /\/etc\/shadow/gi, severity: 'critical' as const, desc: 'Password file access attempt', }, { pattern: /C:\\Windows\\System32/gi, severity: 'high' as const, desc: 'Windows system directory access', }, { pattern: /\/proc\/self\/environ/gi, severity: 'high' as const, desc: 'Environment variable access', }, { pattern: /\/home\/[^/]+\/\.ssh/gi, severity: 'high' as const, desc: 'SSH key directory access', }, ]; for (const { pattern, severity, desc } of pathPatterns) { const matches = input.match(pattern); if (matches) { violations.push({ type: 'path_traversal', description: desc, severity, pattern: pattern.toString(), }); } } return violations; } /** * Detect known malicious patterns */ private detectMaliciousPatterns(input: string): SecurityViolation[] { const violations: SecurityViolation[] = []; for (const pattern of this.knownMaliciousPatterns) { if (pattern.test(input)) { violations.push({ type: 'malicious_pattern', description: `Known malicious pattern detected: ${pattern.toString()}`, severity: 'critical', pattern: pattern.toString(), }); } } return violations; } /** * Analyze content for suspicious patterns */ private async analyzeSuspiciousContent(input: string): Promise<SecurityViolation[]> { const violations: SecurityViolation[] = []; const lowerInput = input.toLowerCase(); // Check for suspicious keywords for (const keyword of this.suspiciousKeywords) { if (lowerInput.includes(keyword)) { violations.push({ type: 'suspicious_content', description: `Suspicious keyword detected: ${keyword}`, severity: 'medium', }); } } // Check for encoded content that might be malicious if (this.detectEncodedMaliciousContent(input)) { violations.push({ type: 'suspicious_content', description: 'Potentially encoded malicious content detected', severity: 'high', }); } // Check for SQL injection patterns const sqlPatterns = [ /union\s+select/gi, /drop\s+table/gi, /delete\s+from/gi, /insert\s+into/gi, /update\s+.*set/gi, /'.*or.*'.*=.*'/gi, ]; for (const pattern of sqlPatterns) { if (pattern.test(input)) { violations.push({ type: 'suspicious_content', description: 'SQL injection pattern detected', severity: 'high', pattern: pattern.toString(), }); } } return violations; } /** * Detect encoded malicious content */ private detectEncodedMaliciousContent(input: string): boolean { try { // Check for base64 encoded content const base64Pattern = /[A-Za-z0-9+/]{20,}={0,2}/g; const base64Matches = input.match(base64Pattern); if (base64Matches) { for (const match of base64Matches) { try { const decoded = Buffer.from(match, 'base64').toString('utf-8'); if (this.containsSuspiciousPatterns(decoded)) { return true; } } catch { // Ignore invalid base64 } } } // Check for URL encoded content const urlEncodedPattern = /%[0-9A-Fa-f]{2}/g; if (urlEncodedPattern.test(input)) { try { const decoded = decodeURIComponent(input); if (this.containsSuspiciousPatterns(decoded)) { return true; } } catch { // Ignore invalid URL encoding } } // Check for hex encoded content const hexPattern = /\\x[0-9A-Fa-f]{2}/g; if (hexPattern.test(input)) { const decoded = input.replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)) ); if (this.containsSuspiciousPatterns(decoded)) { return true; } } } catch (error) { this.logger.warn('Error checking encoded content:', error); } return false; } /** * Check if text contains suspicious patterns */ private containsSuspiciousPatterns(text: string): boolean { const suspiciousPatterns = [ /rm\s+-rf/i, /malicious/i, /exploit/i, /payload/i, /shellcode/i, /backdoor/i, ]; return suspiciousPatterns.some(pattern => pattern.test(text)); } /** * Sanitize input by removing or escaping dangerous content */ private sanitizeInput(input: string, violations: SecurityViolation[]): string { let sanitized = input; // Remove shell metacharacters sanitized = sanitized.replace(/[;&|`$(){}]/g, ''); // Remove path traversal sequences sanitized = sanitized.replace(/\.\.\/+/g, './'); sanitized = sanitized.replace(/\.\.\\+/g, '.\\'); // Remove dangerous commands sanitized = sanitized.replace(/rm\s+-r?f?\s+/gi, '[FILTERED] '); sanitized = sanitized.replace(/curl\s+/gi, '[FILTERED] '); sanitized = sanitized.replace(/wget\s+/gi, '[FILTERED] '); sanitized = sanitized.replace(/sudo\s+/gi, '[FILTERED] '); // Filter out malicious keywords including "malicious" itself const criticalKeywords = ['malicious', 'exploit', 'payload', 'shellcode', 'backdoor']; for (const keyword of criticalKeywords) { const regex = new RegExp(keyword, 'gi'); sanitized = sanitized.replace(regex, '[FILTERED]'); } return sanitized; } /** * Generate security recommendations */ private generateRecommendations( violations: SecurityViolation[], riskLevel: ValidationResult['riskLevel'] ): string[] { const recommendations: string[] = []; if (riskLevel === 'critical') { recommendations.push( 'CRITICAL: Input contains dangerous patterns that could compromise system security' ); recommendations.push( 'Recommend rejecting this input and implementing additional validation layers' ); } if (violations.some(v => v.type === 'command_injection')) { recommendations.push('Implement command whitelisting and input escaping'); recommendations.push('Use sandboxed execution environment for any command execution'); } if (violations.some(v => v.type === 'path_traversal')) { recommendations.push( 'Implement path validation and restrict file access to approved directories' ); recommendations.push('Use absolute paths and canonical path resolution'); } if (violations.some(v => v.type === 'malicious_pattern')) { recommendations.push( 'Content matches known malicious patterns - consider blocking this input' ); recommendations.push('Update malicious pattern database regularly'); } return recommendations; } /** * Get highest severity level from violations */ private getHighestSeverity(violations: SecurityViolation[]): SecurityViolation['severity'] { if (violations.some(v => v.severity === 'critical')) return 'critical'; if (violations.some(v => v.severity === 'high')) return 'high'; if (violations.some(v => v.severity === 'medium')) return 'medium'; return 'low'; } /** * Initialize known malicious patterns */ private initializeMaliciousPatterns(): void { this.knownMaliciousPatterns = [ // Known attack patterns /nc\s+-l.*-e/gi, // Netcat reverse shell /python.*-c.*exec/gi, // Python code execution /perl.*-e/gi, // Perl one-liner /ruby.*-e/gi, // Ruby one-liner /bash.*-c/gi, // Bash command execution /sh.*-c/gi, // Shell command execution /powershell.*-c/gi, // PowerShell execution /cmd.*\/c/gi, // Windows command execution // File operations /echo.*>>.*\/etc\//gi, // Writing to system files /cat.*\/etc\/passwd/gi, // Reading password file /ls.*-la.*\/etc/gi, // Listing system directories // Network operations /wget.*\|\s*sh/gi, // Download and execute /curl.*\|\s*bash/gi, // Download and execute // Process manipulation /kill\s+-9/gi, // Force kill processes /killall/gi, // Kill all processes /pkill/gi, // Pattern-based process killing // System information gathering /uname\s+-a/gi, // System information /whoami/gi, // Current user /id\s*$/gi, // User ID information /ps\s+aux/gi, // Process listing // Privilege escalation /sudo\s+su/gi, // Switch to root /su\s+-/gi, // Switch user /chmod\s+777/gi, // Full permissions /chown\s+root/gi, // Change ownership to root ]; } /** * Initialize suspicious keywords */ private initializeSuspiciousKeywords(): void { this.suspiciousKeywords = [ // Hacking/exploitation terms 'exploit', 'payload', 'shellcode', 'backdoor', 'trojan', 'virus', 'rootkit', 'keylogger', 'botnet', 'ransomware', 'malware', // Attack methods 'injection', 'overflow', 'xss', 'csrf', 'clickjacking', 'phishing', 'spoofing', 'sniffing', 'bruteforce', 'dictionary', 'rainbow', // System compromise 'privilege escalation', 'lateral movement', 'persistence', 'exfiltration', 'command and control', 'c2', 'reverse shell', 'bind shell', // 2024 AI-specific threat keywords 'prompt injection', 'jailbreak', 'ignore previous instructions', 'forget everything', 'new instructions', 'role hijacking', 'system override', 'memory manipulation', 'context switching', // Sensitive operations (context-dependent) 'format disk', 'delete system', 'remove all', 'wipe drive', 'master boot record', 'boot sector', 'partition table', ]; } /** * Merge with default security policy */ private mergeWithDefaultPolicy(policy: Partial<SecurityPolicy>): SecurityPolicy { const defaultPolicy: SecurityPolicy = { allowedCommands: [ 'ls', 'cat', 'grep', 'find', 'head', 'tail', 'wc', 'sort', 'uniq', 'git', 'npm', 'node', 'python', 'pip', 'cargo', 'rustc', 'tsc', 'eslint', 'prettier', 'jest', 'mocha', 'pytest', ], blockedPatterns: [/rm\s+-rf/, /sudo\s+/, /chmod\s+777/, />\s*\/dev\/null/, /2>&1/, /nohup/], maxInputLength: 10000, allowCodeExecution: false, allowFileAccess: true, allowNetworkAccess: false, requireSandbox: true, }; return { ...defaultPolicy, ...policy }; } /** * Update security policy */ updatePolicy(newPolicy: Partial<SecurityPolicy>): void { this.policy = { ...this.policy, ...newPolicy }; this.logger.info('Security policy updated'); } /** * Get current security policy */ getPolicy(): SecurityPolicy { return { ...this.policy }; } /** * Generate security report */ generateSecurityReport(): any { return { policy: this.policy, maliciousPatternsCount: this.knownMaliciousPatterns.length, suspiciousKeywordsCount: this.suspiciousKeywords.length, lastUpdated: new Date().toISOString(), }; } } export default AdvancedSecurityValidator;