UNPKG

claude-flow

Version:

Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)

618 lines (539 loc) 23.4 kB
const { TestHarness } = require('../test-harness'); const assert = require('assert'); describe('Security Mode Batch Integration Tests', () => { let harness; beforeEach(() => { harness = new TestHarness(); harness.createMockProject('complex'); }); afterEach(() => { harness.reset(); }); describe('Concurrent Vulnerability Scanning', () => { it('should scan multiple files for security vulnerabilities in parallel', async () => { // Add files with various security issues const vulnerableFiles = { 'src/auth/login.js': `const sql = "SELECT * FROM users WHERE email = '" + email + "'"; db.query(sql);`, // SQL Injection 'src/api/user.js': `app.get('/user/:id', (req, res) => { res.send('<h1>Welcome ' + req.params.id + '</h1>'); });`, // XSS 'src/utils/crypto.js': `const crypto = require('crypto'); const hash = crypto.createHash('md5');`, // Weak crypto 'src/config/secrets.js': `const API_KEY = 'sk_live_1234567890abcdef'; const DB_PASSWORD = 'admin123';`, // Hardcoded secrets 'src/file/upload.js': `const filePath = '/uploads/' + req.body.filename; fs.readFile(filePath);` // Path traversal }; Object.entries(vulnerableFiles).forEach(([path, content]) => { harness.mockFS.set(path, content); }); const scanResults = await harness.executeBatch( Object.keys(vulnerableFiles), async (file) => { const content = await harness.mockReadFile(file); const vulnerabilities = []; // SQL Injection detection if (content.match(/["']\s*\+.*?["']\s*\+.*?["']/)) { vulnerabilities.push({ type: 'SQL Injection', severity: 'critical', line: 1, confidence: 0.9 }); } // XSS detection if (content.includes('res.send') && content.includes('+ req.')) { vulnerabilities.push({ type: 'Cross-Site Scripting (XSS)', severity: 'high', line: 2, confidence: 0.85 }); } // Weak cryptography if (content.includes("createHash('md5')") || content.includes("createHash('sha1')")) { vulnerabilities.push({ type: 'Weak Cryptography', severity: 'medium', line: 2, confidence: 0.95 }); } // Hardcoded secrets if (content.match(/(?:API_KEY|PASSWORD|SECRET)\s*=\s*["'][^"']+["']/)) { vulnerabilities.push({ type: 'Hardcoded Secrets', severity: 'high', line: 1, confidence: 0.99 }); } // Path traversal if (content.includes('req.body.filename') && content.includes('fs.')) { vulnerabilities.push({ type: 'Path Traversal', severity: 'high', line: 1, confidence: 0.8 }); } return { file, vulnerabilities, riskScore: vulnerabilities.reduce((score, vuln) => { return score + (vuln.severity === 'critical' ? 10 : vuln.severity === 'high' ? 7 : vuln.severity === 'medium' ? 4 : 1); }, 0), needsImmediateAction: vulnerabilities.some(v => v.severity === 'critical') }; } ); assert.strictEqual(scanResults.successful.length, 5); assert(scanResults.successful.every(r => r.vulnerabilities.length > 0)); const criticalFiles = scanResults.successful.filter(r => r.needsImmediateAction); assert(criticalFiles.length >= 1); }); it('should perform dependency vulnerability analysis', async () => { // Mock package files with vulnerable dependencies const packageFiles = { 'package.json': JSON.stringify({ dependencies: { 'express': '3.0.0', // Old version with vulnerabilities 'lodash': '4.17.11', // Version with prototype pollution 'axios': '0.18.0', // Version with SSRF vulnerability 'jsonwebtoken': '8.0.0' // Version with verification bypass } }), 'frontend/package.json': JSON.stringify({ dependencies: { 'react': '16.0.0', // Old version 'jquery': '2.2.4', // Multiple XSS vulnerabilities 'angular': '1.5.0' // Old AngularJS with issues } }), 'services/package.json': JSON.stringify({ dependencies: { 'mongodb': '2.2.0', // Old driver version 'redis': '2.0.0', // Old version 'bcrypt': '1.0.0' // Old version with issues } }) }; Object.entries(packageFiles).forEach(([path, content]) => { harness.mockFS.set(path, content); }); const dependencyAnalysis = await harness.executeBatch( Object.keys(packageFiles), async (packageFile) => { const content = await harness.mockReadFile(packageFile); const pkg = JSON.parse(content); const vulnerabilities = []; // Simulate vulnerability database lookup const vulnDatabase = { 'express': { '3.0.0': [{ cve: 'CVE-2014-6393', severity: 'high' }] }, 'lodash': { '4.17.11': [{ cve: 'CVE-2019-10744', severity: 'critical' }] }, 'axios': { '0.18.0': [{ cve: 'CVE-2019-10742', severity: 'high' }] }, 'jquery': { '2.2.4': [{ cve: 'CVE-2015-9251', severity: 'medium' }] }, 'angular': { '1.5.0': [{ cve: 'CVE-2016-4855', severity: 'high' }] } }; for (const [dep, version] of Object.entries(pkg.dependencies || {})) { if (vulnDatabase[dep] && vulnDatabase[dep][version]) { vulnerabilities.push({ package: dep, version, vulnerabilities: vulnDatabase[dep][version], severity: vulnDatabase[dep][version][0].severity }); } } return { file: packageFile, totalDependencies: Object.keys(pkg.dependencies || {}).length, vulnerableDependencies: vulnerabilities.length, vulnerabilities, riskLevel: vulnerabilities.some(v => v.severity === 'critical') ? 'critical' : vulnerabilities.some(v => v.severity === 'high') ? 'high' : 'medium' }; } ); assert.strictEqual(dependencyAnalysis.successful.length, 3); const totalVulnerabilities = dependencyAnalysis.successful.reduce( (sum, r) => sum + r.vulnerableDependencies, 0 ); assert(totalVulnerabilities >= 5); }); it('should analyze authentication and authorization patterns', async () => { // Add auth-related files const authFiles = { 'src/middleware/auth.js': `export function authenticate(req, res, next) { const token = req.headers.authorization; if (!token) return res.status(401).send('No token'); // Missing token validation next(); }`, 'src/routes/admin.js': `router.get('/admin', (req, res) => { // No authorization check res.render('admin-panel'); })`, 'src/services/session.js': `sessions[userId] = { token: generateToken(), expires: Date.now() + 3600000 // 1 hour // No session invalidation mechanism }`, 'src/utils/password.js': `function hashPassword(password) { return btoa(password); // Base64 is not encryption! }` }; Object.entries(authFiles).forEach(([path, content]) => { harness.mockFS.set(path, content); }); const authAnalysis = await harness.executeBatch( Object.keys(authFiles), async (file) => { const content = await harness.mockReadFile(file); const issues = []; // Check for missing token validation if (content.includes('authorization') && !content.includes('verify') && !content.includes('decode')) { issues.push({ type: 'Missing Token Validation', severity: 'critical', recommendation: 'Implement proper JWT validation' }); } // Check for missing authorization if (content.includes('/admin') && !content.includes('role') && !content.includes('permission')) { issues.push({ type: 'Missing Authorization Check', severity: 'high', recommendation: 'Add role-based access control' }); } // Check for session management issues if (content.includes('sessions[') && !content.includes('invalidate') && !content.includes('delete')) { issues.push({ type: 'Poor Session Management', severity: 'medium', recommendation: 'Implement session invalidation' }); } // Check for weak password handling if (content.includes('btoa') || content.includes('atob')) { issues.push({ type: 'Insecure Password Storage', severity: 'critical', recommendation: 'Use bcrypt or argon2 for password hashing' }); } return { file, authIssues: issues, securityScore: Math.max(0, 100 - (issues.length * 25)), compliant: issues.length === 0 }; } ); assert.strictEqual(authAnalysis.successful.length, 4); assert(authAnalysis.successful.every(r => r.authIssues.length > 0)); const criticalIssues = authAnalysis.successful .flatMap(r => r.authIssues) .filter(i => i.severity === 'critical'); assert(criticalIssues.length >= 2); }); }); describe('Concurrent OWASP Top 10 Analysis', () => { it('should check for OWASP Top 10 vulnerabilities in parallel', async () => { const owaspCategories = [ { id: 'A01', name: 'Broken Access Control' }, { id: 'A02', name: 'Cryptographic Failures' }, { id: 'A03', name: 'Injection' }, { id: 'A04', name: 'Insecure Design' }, { id: 'A05', name: 'Security Misconfiguration' }, { id: 'A06', name: 'Vulnerable Components' }, { id: 'A07', name: 'Authentication Failures' }, { id: 'A08', name: 'Data Integrity Failures' }, { id: 'A09', name: 'Security Logging Failures' }, { id: 'A10', name: 'SSRF' } ]; const owaspAnalysis = await harness.executeBatch(owaspCategories, async (category) => { const findings = []; const files = Array.from(harness.mockFS.keys()); for (const file of files) { const content = await harness.mockReadFile(file); switch (category.id) { case 'A01': // Broken Access Control if (content.includes('role') === false && content.includes('admin')) { findings.push({ file, issue: 'Missing access control' }); } break; case 'A02': // Cryptographic Failures if (content.includes('md5') || content.includes('sha1')) { findings.push({ file, issue: 'Weak cryptography' }); } break; case 'A03': // Injection if (content.includes("' +") && content.includes('query')) { findings.push({ file, issue: 'Potential SQL injection' }); } break; case 'A07': // Authentication Failures if (content.includes('password') && !content.includes('hash')) { findings.push({ file, issue: 'Unhashed password' }); } break; } } return { category: category.id, name: category.name, findings, risk: findings.length > 5 ? 'high' : findings.length > 0 ? 'medium' : 'low', score: Math.max(0, 100 - (findings.length * 10)) }; }); assert.strictEqual(owaspAnalysis.successful.length, 10); const highRiskCategories = owaspAnalysis.successful.filter(r => r.risk === 'high'); assert(highRiskCategories.length >= 0); // May vary based on mock data // Calculate overall OWASP compliance score const overallScore = owaspAnalysis.successful.reduce((sum, r) => sum + r.score, 0) / 10; console.log(`OWASP Compliance Score: ${overallScore.toFixed(1)}%`); }); }); describe('Security Headers Analysis', () => { it('should analyze security headers across multiple endpoints', async () => { // Mock API endpoint files const endpoints = { 'src/routes/auth.js': `router.post('/login', (req, res) => { res.json({ token: 'xyz' }); })`, 'src/routes/api.js': `router.get('/data', (req, res) => { res.setHeader('X-Content-Type-Options', 'nosniff'); res.json({ data: [] }); })`, 'src/routes/public.js': `router.get('/home', (req, res) => { res.setHeader('X-Frame-Options', 'DENY'); res.setHeader('Content-Security-Policy', "default-src 'self'"); res.render('home'); })` }; Object.entries(endpoints).forEach(([path, content]) => { harness.mockFS.set(path, content); }); const requiredHeaders = [ 'X-Content-Type-Options', 'X-Frame-Options', 'Content-Security-Policy', 'Strict-Transport-Security', 'X-XSS-Protection' ]; const headerAnalysis = await harness.executeBatch( Object.keys(endpoints), async (endpoint) => { const content = await harness.mockReadFile(endpoint); const presentHeaders = requiredHeaders.filter(header => content.includes(header) ); const missingHeaders = requiredHeaders.filter(header => !presentHeaders.includes(header) ); return { endpoint, presentHeaders, missingHeaders, score: (presentHeaders.length / requiredHeaders.length) * 100, compliant: presentHeaders.length === requiredHeaders.length }; } ); assert.strictEqual(headerAnalysis.successful.length, 3); const compliantEndpoints = headerAnalysis.successful.filter(r => r.compliant); assert(compliantEndpoints.length <= 1); // Most endpoints missing headers }); }); describe('Concurrent Input Validation Analysis', () => { it('should analyze input validation patterns across forms and APIs', async () => { const inputHandlers = { 'src/api/user-create.js': `app.post('/user', (req, res) => { const { email, password, age } = req.body; // No validation db.createUser(email, password, age); })`, 'src/api/search.js': `app.get('/search', (req, res) => { const query = req.query.q; if (query.length > 100) return res.status(400).send('Query too long'); db.search(query); })`, 'src/forms/register.js': `function validateForm(data) { if (!data.email.match(/^[^@]+@[^@]+$/)) return false; if (data.password.length < 8) return false; return true; }`, 'src/api/file-upload.js': `app.post('/upload', (req, res) => { const file = req.files.upload; // No file type validation file.mv('/uploads/' + file.name); })` }; Object.entries(inputHandlers).forEach(([path, content]) => { harness.mockFS.set(path, content); }); const validationAnalysis = await harness.executeBatch( Object.keys(inputHandlers), async (handler) => { const content = await harness.mockReadFile(handler); const validationIssues = []; // Check for email validation if (content.includes('email') && !content.includes('match') && !content.includes('validate')) { validationIssues.push({ field: 'email', issue: 'Missing email validation', severity: 'high' }); } // Check for password validation if (content.includes('password') && !content.includes('length')) { validationIssues.push({ field: 'password', issue: 'Missing password strength check', severity: 'high' }); } // Check for file upload validation if (content.includes('upload') && !content.includes('type') && !content.includes('extension')) { validationIssues.push({ field: 'file', issue: 'Missing file type validation', severity: 'critical' }); } // Check for SQL injection prevention if (content.includes('req.') && !content.includes('escape') && !content.includes('sanitize')) { validationIssues.push({ field: 'general', issue: 'No input sanitization', severity: 'critical' }); } return { handler, validationIssues, hasValidation: content.includes('validate') || content.includes('match') || content.includes('length'), riskLevel: validationIssues.some(i => i.severity === 'critical') ? 'critical' : validationIssues.length > 2 ? 'high' : 'medium' }; } ); assert.strictEqual(validationAnalysis.successful.length, 4); const criticalHandlers = validationAnalysis.successful.filter(r => r.riskLevel === 'critical'); assert(criticalHandlers.length >= 1); }); }); describe('Security Report Generation', () => { it('should generate comprehensive security reports in parallel', async () => { const reportTypes = [ { type: 'executive-summary', format: 'pdf' }, { type: 'technical-details', format: 'html' }, { type: 'vulnerability-list', format: 'json' }, { type: 'remediation-plan', format: 'md' }, { type: 'compliance-matrix', format: 'csv' } ]; const reportGeneration = await harness.executeBatch(reportTypes, async (report) => { await harness.simulateDelay(100); // Simulate report generation let content = ''; let stats = {}; switch (report.type) { case 'executive-summary': content = `# Security Assessment Executive Summary\n\n` + `Critical Issues: 3\n` + `High Risk Issues: 7\n` + `Overall Risk Score: 65/100\n`; stats = { pages: 5, sections: 4 }; break; case 'technical-details': content = `<html><body><h1>Technical Security Report</h1>` + `<p>Detailed findings...</p></body></html>`; stats = { pages: 25, findings: 45 }; break; case 'vulnerability-list': content = JSON.stringify({ vulnerabilities: [ { id: 'VULN-001', severity: 'critical', type: 'SQL Injection' }, { id: 'VULN-002', severity: 'high', type: 'XSS' } ] }); stats = { vulnerabilities: 15 }; break; case 'remediation-plan': content = `# Remediation Plan\n\n` + `## Priority 1: Critical Issues\n` + `- Fix SQL injection in auth module\n` + `- Update vulnerable dependencies\n`; stats = { tasks: 20, estimatedDays: 10 }; break; case 'compliance-matrix': content = `Standard,Requirement,Status,Notes\n` + `OWASP,A01,FAIL,Missing access controls\n` + `PCI-DSS,3.4,PASS,Encryption implemented\n`; stats = { standards: 3, requirements: 50 }; break; } const filename = `security-report-${report.type}.${report.format}`; await harness.mockWriteFile(`reports/${filename}`, content); return { report: report.type, format: report.format, filename, size: content.length, stats, generated: true }; }); assert.strictEqual(reportGeneration.successful.length, 5); assert(reportGeneration.successful.every(r => r.generated)); // Verify all report types were generated const reportFormats = reportGeneration.successful.map(r => r.format); assert(reportFormats.includes('pdf')); assert(reportFormats.includes('json')); assert(reportFormats.includes('csv')); }); }); describe('Performance Impact', () => { it('should demonstrate parallel security scanning performance', async () => { // Create a larger codebase for performance testing const fileCount = 50; for (let i = 0; i < fileCount; i++) { harness.mockFS.set(`src/module${i}.js`, ` const password = 'pass${i}'; const query = "SELECT * FROM table WHERE id = " + id; eval(userInput); `); } const files = Array.from(harness.mockFS.keys()).filter(f => f.includes('module')); // Sequential scanning harness.concurrencyLimit = 1; const sequentialStart = Date.now(); await harness.executeBatch(files, async (file) => { const content = await harness.mockReadFile(file); await harness.simulateDelay(20); // Simulate scanning time return { file, scanned: true }; }); const sequentialTime = Date.now() - sequentialStart; // Parallel scanning harness.concurrencyLimit = 10; const parallelStart = Date.now(); await harness.executeBatch(files, async (file) => { const content = await harness.mockReadFile(file); await harness.simulateDelay(20); return { file, scanned: true }; }); const parallelTime = Date.now() - parallelStart; const speedup = sequentialTime / parallelTime; assert(speedup > 4, `Expected speedup > 4x, got ${speedup.toFixed(2)}x`); console.log(`Security scanning speedup: ${speedup.toFixed(2)}x`); console.log(`Files scanned: ${files.length}`); console.log(`Sequential time: ${sequentialTime}ms`); console.log(`Parallel time: ${parallelTime}ms`); }); }); });