UNPKG

vineguard-mcp-server-standalone

Version:

VineGuard MCP Server v2.1 - Intelligent QA Workflow System with advanced test generation for Jest/RTL, Cypress, and Playwright. Features smart project analysis, progressive testing strategies, and comprehensive quality patterns for React/Vue/Angular proje

450 lines 18.9 kB
/** * Security audit tool for VineGuard MCP Server * Comprehensive security scanning and vulnerability detection */ import * as fs from 'fs/promises'; import * as path from 'path'; import { spawn } from 'child_process'; export class SecurityAuditor { static SECURITY_PATTERNS = [ // Injection vulnerabilities { pattern: /eval\s*\(/g, type: 'vulnerability', severity: 'critical', title: 'Code Injection - eval() usage', description: 'Use of eval() can lead to code injection vulnerabilities', suggestion: 'Replace eval() with safer alternatives like JSON.parse() or specific parsing logic', cwe: 'CWE-94', cvss: 9.0 }, { pattern: /new\s+Function\s*\(/g, type: 'vulnerability', severity: 'high', title: 'Code Injection - Function constructor', description: 'Dynamic function creation can be exploited for code injection', suggestion: 'Avoid dynamic function creation or use safer alternatives', cwe: 'CWE-94', cvss: 7.5 }, { pattern: /document\.write\s*\(/g, type: 'vulnerability', severity: 'medium', title: 'XSS Risk - document.write', description: 'document.write can be exploited for XSS attacks', suggestion: 'Use safer DOM manipulation methods like createElement', cwe: 'CWE-79', cvss: 6.1 }, { pattern: /innerHTML\s*=/g, type: 'security-risk', severity: 'medium', title: 'XSS Risk - innerHTML assignment', description: 'Direct innerHTML assignment can lead to XSS if data is not sanitized', suggestion: 'Use textContent or sanitize HTML content before assignment', cwe: 'CWE-79', cvss: 6.1 }, // Cryptographic issues { pattern: /Math\.random\s*\(\)/g, type: 'security-risk', severity: 'medium', title: 'Weak Random Number Generation', description: 'Math.random() is not cryptographically secure', suggestion: 'Use crypto.randomBytes() or crypto.getRandomValues() for security-sensitive operations', cwe: 'CWE-338', cvss: 5.3 }, { pattern: /md5|sha1(?!.*sha1[0-9])/gi, type: 'security-risk', severity: 'medium', title: 'Weak Cryptographic Hash', description: 'MD5 and SHA1 are cryptographically broken', suggestion: 'Use SHA-256 or stronger hash functions', cwe: 'CWE-327', cvss: 5.9 }, // Command injection { pattern: /exec\s*\(/g, type: 'vulnerability', severity: 'high', title: 'Command Injection Risk - exec()', description: 'exec() with user input can lead to command injection', suggestion: 'Use spawn() with argument arrays or validate/sanitize all inputs', cwe: 'CWE-78', cvss: 8.1 }, { pattern: /system\s*\(/g, type: 'vulnerability', severity: 'high', title: 'Command Injection Risk - system()', description: 'system() calls can be exploited for command injection', suggestion: 'Use safer alternatives like spawn() with proper input validation', cwe: 'CWE-78', cvss: 8.1 }, // Path traversal { pattern: /\.\.[\/\\]/g, type: 'security-risk', severity: 'high', title: 'Path Traversal Risk', description: 'Path traversal sequences detected', suggestion: 'Validate and sanitize file paths, use path.resolve() and check bounds', cwe: 'CWE-22', cvss: 7.5 }, // Information disclosure { pattern: /console\.(log|error|warn|info)\s*\(/g, type: 'best-practice', severity: 'low', title: 'Information Disclosure - Console Logging', description: 'Console logs may expose sensitive information in production', suggestion: 'Remove debug logs before production or use proper logging frameworks', cwe: 'CWE-532', cvss: 2.1 }, { pattern: /password|secret|key|token.*=.*['"][^'"]+['"]/gi, type: 'vulnerability', severity: 'critical', title: 'Hardcoded Secrets', description: 'Potential hardcoded secrets detected', suggestion: 'Move secrets to environment variables or secure configuration', cwe: 'CWE-798', cvss: 9.8 }, // Prototype pollution { pattern: /__proto__|constructor\.prototype|Object\.prototype/g, type: 'vulnerability', severity: 'high', title: 'Prototype Pollution Risk', description: 'Potential prototype pollution vulnerability', suggestion: 'Avoid modifying object prototypes, use Object.create(null) for safe objects', cwe: 'CWE-1321', cvss: 7.5 }, // CORS issues { pattern: /Access-Control-Allow-Origin.*\*/g, type: 'security-risk', severity: 'medium', title: 'Overly Permissive CORS', description: 'Wildcard CORS policy detected', suggestion: 'Specify explicit origins instead of using wildcards', cwe: 'CWE-942', cvss: 5.3 }, // SQL Injection (for projects that might use SQL) { pattern: /query.*\+.*|SELECT.*\+.*|INSERT.*\+.*/gi, type: 'vulnerability', severity: 'critical', title: 'SQL Injection Risk', description: 'Potential SQL injection vulnerability detected', suggestion: 'Use parameterized queries or prepared statements', cwe: 'CWE-89', cvss: 9.0 } ]; /** * Perform comprehensive security audit */ static async auditProject(projectPath, options = {}) { const { includeNodeModules = false, includeDependencyAudit = true, maxFileSize = 1024 * 1024 // 1MB } = options; const result = { projectPath, scannedFiles: 0, totalIssues: 0, issuesBySeverity: { critical: 0, high: 0, medium: 0, low: 0, info: 0 }, issues: [], securityScore: 100, recommendations: [], scannedAt: new Date().toISOString() }; try { // Find all relevant files const files = await this.findFiles(projectPath, includeNodeModules); // Scan each file for security issues for (const file of files) { try { const stats = await fs.stat(file); if (stats.size > maxFileSize) { continue; // Skip large files } const content = await fs.readFile(file, 'utf-8'); const fileIssues = this.scanFileContent(content, file); result.issues.push(...fileIssues); result.scannedFiles++; } catch (error) { console.error(`Error scanning file ${file}:`, error); } } // Perform dependency audit if requested if (includeDependencyAudit) { result.dependencyAudit = await this.auditDependencies(projectPath); } // Calculate statistics this.calculateStatistics(result); // Generate recommendations result.recommendations = this.generateRecommendations(result); } catch (error) { throw new Error(`Security audit failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } return result; } /** * Scan file content for security issues */ static scanFileContent(content, filePath) { const issues = []; const lines = content.split('\n'); for (const pattern of this.SECURITY_PATTERNS) { let match; const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags); while ((match = regex.exec(content)) !== null) { // Find the line number const beforeMatch = content.substring(0, match.index); const lineNumber = beforeMatch.split('\n').length; issues.push({ type: pattern.type, severity: pattern.severity, title: pattern.title, description: pattern.description, file: filePath, line: lineNumber, suggestion: pattern.suggestion, cwe: pattern.cwe, cvss: pattern.cvss }); } } // Additional file-specific checks issues.push(...this.performAdditionalChecks(content, filePath)); return issues; } /** * Perform additional security checks */ static performAdditionalChecks(content, filePath) { const issues = []; // Check for package.json security issues if (filePath.endsWith('package.json')) { try { const packageData = JSON.parse(content); // Check for scripts that might be dangerous if (packageData.scripts) { for (const [scriptName, scriptContent] of Object.entries(packageData.scripts)) { if (typeof scriptContent === 'string' && /rm\s+-rf|del\s+\/s|format\s+c:|sudo/.test(scriptContent)) { issues.push({ type: 'security-risk', severity: 'high', title: 'Dangerous npm script', description: `Script "${scriptName}" contains potentially dangerous commands`, file: filePath, suggestion: 'Review and validate npm scripts for security risks', cwe: 'CWE-78' }); } } } // Check for dependencies with known issues const allDeps = { ...packageData.dependencies, ...packageData.devDependencies }; const dangerousDeps = ['lodash@4.17.15', 'debug@2.6.8', 'minimist@1.2.0']; for (const [dep, version] of Object.entries(allDeps)) { if (dangerousDeps.some(dangerous => `${dep}@${version}` === dangerous)) { issues.push({ type: 'dependency-issue', severity: 'high', title: 'Vulnerable dependency', description: `Dependency ${dep}@${version} has known vulnerabilities`, file: filePath, suggestion: 'Update to a secure version of this dependency' }); } } } catch (error) { // Invalid JSON, but not necessarily a security issue } } // Check for environment files with suspicious content if (filePath.includes('.env')) { const suspiciousEnvPatterns = [ /DATABASE_URL.*localhost/gi, /DEBUG.*true/gi, /NODE_ENV.*development/gi ]; for (const pattern of suspiciousEnvPatterns) { if (pattern.test(content)) { issues.push({ type: 'best-practice', severity: 'medium', title: 'Development configuration in env file', description: 'Environment file contains development-specific settings', file: filePath, suggestion: 'Ensure production environment files don\'t contain development settings' }); } } } return issues; } /** * Find all relevant files for security scanning */ static async findFiles(dir, includeNodeModules) { const files = []; const extensions = ['.js', '.ts', '.jsx', '.tsx', '.json', '.env', '.config.js', '.config.ts']; async function scanDirectory(currentDir) { try { const items = await fs.readdir(currentDir); for (const item of items) { const fullPath = path.join(currentDir, item); const stats = await fs.stat(fullPath); if (stats.isDirectory()) { if (!includeNodeModules && (item === 'node_modules' || item === '.git')) { continue; } await scanDirectory(fullPath); } else if (stats.isFile()) { const ext = path.extname(item); if (extensions.includes(ext) || item.startsWith('.env')) { files.push(fullPath); } } } } catch (error) { // Skip directories we can't read } } await scanDirectory(dir); return files; } /** * Audit npm dependencies for vulnerabilities */ static async auditDependencies(projectPath) { return new Promise((resolve) => { const packageJsonPath = path.join(projectPath, 'package.json'); // Check if package.json exists fs.access(packageJsonPath).then(() => { // Try to run npm audit const audit = spawn('npm', ['audit', '--json'], { cwd: projectPath, stdio: 'pipe' }); let output = ''; audit.stdout?.on('data', (data) => { output += data.toString(); }); audit.on('close', (code) => { try { if (output.trim()) { const auditResult = JSON.parse(output); const vulnerabilities = auditResult.metadata?.vulnerabilities?.total || 0; resolve({ vulnerabilities, outdatedPackages: 0, // Would need separate npm outdated check recommendations: [ vulnerabilities > 0 ? 'Run npm audit fix to resolve vulnerabilities' : 'No known vulnerabilities found', 'Regularly update dependencies to latest secure versions', 'Consider using npm ci in production for reproducible builds' ] }); } else { resolve({ vulnerabilities: 0, outdatedPackages: 0, recommendations: ['Could not perform dependency audit - no package.json or npm not available'] }); } } catch (error) { resolve({ vulnerabilities: 0, outdatedPackages: 0, recommendations: ['Dependency audit failed - ensure npm is installed and package.json is valid'] }); } }); }).catch(() => { resolve({ vulnerabilities: 0, outdatedPackages: 0, recommendations: ['No package.json found - skipping dependency audit'] }); }); }); } /** * Calculate security statistics */ static calculateStatistics(result) { result.totalIssues = result.issues.length; // Count issues by severity for (const issue of result.issues) { result.issuesBySeverity[issue.severity]++; } // Calculate security score (0-100) let score = 100; score -= result.issuesBySeverity.critical * 20; score -= result.issuesBySeverity.high * 10; score -= result.issuesBySeverity.medium * 5; score -= result.issuesBySeverity.low * 2; score -= result.issuesBySeverity.info * 1; // Factor in dependency vulnerabilities if (result.dependencyAudit) { score -= result.dependencyAudit.vulnerabilities * 5; } result.securityScore = Math.max(0, score); } /** * Generate security recommendations */ static generateRecommendations(result) { const recommendations = []; if (result.issuesBySeverity.critical > 0) { recommendations.push('URGENT: Address critical security vulnerabilities immediately'); } if (result.issuesBySeverity.high > 0) { recommendations.push('Address high-severity security issues as soon as possible'); } if (result.issuesBySeverity.medium > 0) { recommendations.push('Review and fix medium-severity security issues'); } if (result.securityScore < 70) { recommendations.push('Consider implementing a security-first development approach'); recommendations.push('Add security linting to your CI/CD pipeline'); } if (result.dependencyAudit && result.dependencyAudit.vulnerabilities > 0) { recommendations.push('Update vulnerable dependencies'); } recommendations.push('Implement regular security audits in your development workflow'); recommendations.push('Consider using security-focused tools like ESLint security plugins'); recommendations.push('Follow OWASP security guidelines for your technology stack'); return recommendations; } } //# sourceMappingURL=security-audit.js.map