UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

557 lines 23.8 kB
/** * OWASP Security Analyzer * Checks for OWASP Top 10 vulnerabilities and compliance */ import fs from 'fs-extra'; import * as path from 'path'; import { glob } from 'glob'; export class OWASPAnalyzer { projectRoot; constructor(projectRoot) { this.projectRoot = projectRoot; } async analyze(vulnerabilities) { await this.checkOWASPTop10(vulnerabilities); // Advanced checks await this.checkSQLInjection(vulnerabilities); await this.checkXSS(vulnerabilities); await this.checkCSRF(vulnerabilities); await this.checkInsecureDeserialization(vulnerabilities); await this.checkSecurityHeaders(vulnerabilities); await this.checkAuthenticationFlaws(vulnerabilities); await this.checkSessionManagement(vulnerabilities); await this.checkInputValidation(vulnerabilities); await this.checkOutputEncoding(vulnerabilities); await this.checkAccessControl(vulnerabilities); } async analyzeCompliance(vulnerabilities) { const findings = []; const categoryScores = {}; // OWASP Top 10 2021 Categories const categories = [ 'A01:2021 - Broken Access Control', 'A02:2021 - Cryptographic Failures', 'A03:2021 - Injection', 'A04:2021 - Insecure Design', 'A05:2021 - Security Misconfiguration', 'A06:2021 - Vulnerable and Outdated Components', 'A07:2021 - Identification and Authentication Failures', 'A08:2021 - Software and Data Integrity Failures', 'A09:2021 - Security Logging and Monitoring Failures', 'A10:2021 - Server-Side Request Forgery (SSRF)' ]; // Initialize category scores for (const category of categories) { categoryScores[category] = { score: 100, issues: 0, critical: 0, recommendations: [] }; } // Process vulnerabilities into findings for (const vuln of vulnerabilities) { const category = this.mapToOWASPCategory(vuln.type); if (category) { const finding = { category, rule: vuln.type, severity: vuln.severity, file: vuln.file, line: vuln.line, description: vuln.message, impact: this.getImpactDescription(vuln.type, vuln.severity), remediation: vuln.recommendation || this.getRemediationAdvice(vuln.type), cwe: this.mapToCWE(vuln.type), cvss: this.calculateCVSS(vuln.severity) }; findings.push(finding); // Update category scores if (categoryScores[category]) { categoryScores[category].issues++; if (vuln.severity === 'critical') { categoryScores[category].critical++; categoryScores[category].score -= 25; } else if (vuln.severity === 'high') { categoryScores[category].score -= 15; } else if (vuln.severity === 'medium') { categoryScores[category].score -= 8; } else { categoryScores[category].score -= 3; } categoryScores[category].score = Math.max(0, categoryScores[category].score); } } } // Add recommendations for each category for (const category of categories) { categoryScores[category].recommendations = this.getCategoryRecommendations(category, categoryScores[category]); } // Calculate overall compliance const scores = Object.values(categoryScores).map((c) => c.score); const overallCompliance = scores.reduce((sum, score) => sum + score, 0) / scores.length; return { overallCompliance: Math.round(overallCompliance), categoryScores, detailedFindings: findings }; } async checkOWASPTop10(vulnerabilities) { // OWASP Top 10 2021 patterns const owaspPatterns = [ // A01: Broken Access Control { pattern: /\.authorization\s*=\s*false|\.authenticate\s*=\s*false/i, type: 'broken_access_control', message: 'Potential broken access control - authorization/authentication disabled', severity: 'high' }, { pattern: /if\s*\(\s*true\s*\)\s*{[\s\S]*?auth|if\s*\(\s*false\s*\)\s*{[\s\S]*?auth/i, type: 'broken_access_control', message: 'Authorization checks bypassed with hardcoded conditions', severity: 'critical' }, // A02: Cryptographic Failures { pattern: /password\s*=\s*['"]\w+['"]|secret\s*=\s*['"]\w+['"]/i, type: 'cryptographic_failure', message: 'Hardcoded password or secret detected', severity: 'critical' }, { pattern: /MD5|SHA1(?![\w-])/i, type: 'cryptographic_failure', message: 'Weak cryptographic algorithm detected (MD5/SHA1)', severity: 'high' }, // A03: Injection { pattern: /eval\s*\(|new\s+Function\s*\(|document\.write\s*\(/, type: 'injection', message: 'Potential code injection vulnerability (eval, Function constructor, document.write)', severity: 'high' }, { pattern: /innerHTML\s*=\s*[^;]+\+|outerHTML\s*=\s*[^;]+\+/, type: 'xss_injection', message: 'Potential XSS via innerHTML/outerHTML with concatenation', severity: 'high' }, // A04: Insecure Design { pattern: /express\(\)(?![\s\S]*helmet)/, type: 'insecure_design', message: 'Express app without security headers (helmet middleware)', severity: 'medium' }, // A05: Security Misconfiguration { pattern: /\.listen\s*\(\s*80\s*\)|\.listen\s*\(\s*8080\s*\)/, type: 'security_misconfiguration', message: 'HTTP server without HTTPS configuration', severity: 'medium' }, { pattern: /cors\s*:\s*{\s*origin\s*:\s*['"]\*['"]/, type: 'security_misconfiguration', message: 'CORS misconfiguration - allows all origins', severity: 'high' }, // A07: Identification and Authentication Failures { pattern: /session\s*\.\s*regenerate\s*\(\s*\)/, type: 'auth_failure', message: 'Session regeneration without proper error handling', severity: 'medium' }, { pattern: /password\.length\s*<\s*[1-7]\b/, type: 'auth_failure', message: 'Weak password policy - minimum length too short', severity: 'medium' }, // A08: Software and Data Integrity Failures { pattern: /require\s*\(\s*['"]\s*https?:\/\/|import\s+.*from\s+['"]\s*https?:\/\//, type: 'integrity_failure', message: 'Loading code from external URLs without integrity checks', severity: 'high' }, // A09: Security Logging and Monitoring Failures { pattern: /try\s*\{[\s\S]*?\}\s*catch\s*\([^)]*\)\s*\{\s*\}/, type: 'logging_failure', message: 'Empty catch block - security events may go unlogged', severity: 'low' }, // A10: Server-Side Request Forgery (SSRF) { pattern: /fetch\s*\(\s*req\.|axios\s*\(\s*req\.|request\s*\(\s*req\./, type: 'ssrf', message: 'Potential SSRF - HTTP request with user-controlled URL', severity: 'high' } ]; await this.scanForPatterns(vulnerabilities, owaspPatterns); } async checkSQLInjection(vulnerabilities) { const sqlInjectionPatterns = [ { pattern: /['"]\s*\+\s*\w+\s*\+\s*['"][^;]*(?:SELECT|INSERT|UPDATE|DELETE|DROP)/i, type: 'sql_injection', message: 'SQL injection vulnerability - string concatenation in SQL query', severity: 'critical' }, { pattern: /query\s*\(\s*['"][^'"]*['"]\s*\+\s*\w+/i, type: 'sql_injection', message: 'SQL injection vulnerability - concatenated query parameter', severity: 'critical' }, { pattern: /\$\{[^}]*\}.*(?:SELECT|INSERT|UPDATE|DELETE|DROP)/i, type: 'sql_injection', message: 'SQL injection vulnerability - template literal in SQL query', severity: 'critical' }, { pattern: /format\s*\([^)]*(?:SELECT|INSERT|UPDATE|DELETE|DROP)/i, type: 'sql_injection', message: 'SQL injection vulnerability - string formatting in SQL query', severity: 'high' } ]; await this.scanForPatterns(vulnerabilities, sqlInjectionPatterns); } async checkXSS(vulnerabilities) { const xssPatterns = [ { pattern: /innerHTML\s*=\s*[^;]*\+\s*\w+|innerHTML\s*=\s*\w+\s*\+/, type: 'xss', message: 'XSS vulnerability - unescaped content in innerHTML', severity: 'high' }, { pattern: /dangerouslySetInnerHTML\s*:\s*\{\s*__html\s*:\s*\w+/, type: 'xss', message: 'XSS vulnerability - unvalidated dangerouslySetInnerHTML', severity: 'high' }, { pattern: /document\.write\s*\(\s*\w+|document\.writeln\s*\(\s*\w+/, type: 'xss', message: 'XSS vulnerability - document.write with user input', severity: 'high' }, { pattern: /\$\(\s*['"][^'"]*['"]\s*\)\s*\.html\s*\(\s*\w+/, type: 'xss', message: 'XSS vulnerability - jQuery html() with user input', severity: 'high' } ]; await this.scanForPatterns(vulnerabilities, xssPatterns); } async checkCSRF(vulnerabilities) { const csrfPatterns = [ { pattern: /app\.use\s*\(\s*express\.urlencoded(?![\s\S]*csrf)/, type: 'csrf', message: 'CSRF vulnerability - Express app without CSRF protection', severity: 'medium' }, { pattern: /method\s*=\s*["']POST["'](?![\s\S]*csrf)/i, type: 'csrf', message: 'POST form without CSRF token', severity: 'medium' } ]; await this.scanForPatterns(vulnerabilities, csrfPatterns); } async checkInsecureDeserialization(vulnerabilities) { const patterns = [ { pattern: /JSON\.parse\s*\(\s*req\.|JSON\.parse\s*\(\s*request\./, type: 'insecure_deserialization', message: 'Potential insecure deserialization of user input', severity: 'high' }, { pattern: /unserialize\s*\(/, type: 'insecure_deserialization', message: 'Insecure deserialization using unserialize()', severity: 'critical' } ]; await this.scanForPatterns(vulnerabilities, patterns); } async checkSecurityHeaders(vulnerabilities) { const patterns = [ { pattern: /res\.setHeader\s*\(\s*['"]X-Frame-Options['"]/i, type: 'security_headers', message: 'Good: X-Frame-Options header is set', severity: 'low', positive: true }, { pattern: /app\.listen(?![\s\S]*helmet)/, type: 'missing_security_headers', message: 'Missing security headers - consider using helmet', severity: 'medium' } ]; await this.scanForPatterns(vulnerabilities, patterns.filter(p => !p.positive)); } async checkAuthenticationFlaws(vulnerabilities) { const patterns = [ { pattern: /bcrypt\.compare\s*\(\s*password\s*,\s*['"][^'"]+['"]\s*\)/, type: 'auth_flaw', message: 'Hardcoded password hash in authentication', severity: 'critical' }, { pattern: /jwt\.sign\s*\([^)]*secret\s*:\s*['"][^'"]+['"]/, type: 'auth_flaw', message: 'Hardcoded JWT secret', severity: 'critical' } ]; await this.scanForPatterns(vulnerabilities, patterns); } async checkSessionManagement(vulnerabilities) { const patterns = [ { pattern: /session\s*:\s*{[^}]*httpOnly\s*:\s*false/, type: 'session_management', message: 'Session cookie without httpOnly flag', severity: 'high' }, { pattern: /session\s*:\s*{[^}]*secure\s*:\s*false/, type: 'session_management', message: 'Session cookie without secure flag', severity: 'medium' } ]; await this.scanForPatterns(vulnerabilities, patterns); } async checkInputValidation(vulnerabilities) { const patterns = [ { pattern: /req\.\w+\[['"][^'"]+['"]\](?!\s*\.\s*(?:trim|escape|sanitize))/, type: 'input_validation', message: 'User input used without validation', severity: 'medium' }, { pattern: /parseInt\s*\(\s*req\.|parseFloat\s*\(\s*req\./, type: 'input_validation', message: 'Numeric parsing of user input without validation', severity: 'low' } ]; await this.scanForPatterns(vulnerabilities, patterns); } async checkOutputEncoding(vulnerabilities) { const patterns = [ { pattern: /res\.send\s*\(\s*req\.|res\.json\s*\(\s*req\./, type: 'output_encoding', message: 'User input sent directly in response', severity: 'medium' }, { pattern: /res\.write\s*\(\s*[^)]*\+\s*req\./, type: 'output_encoding', message: 'User input concatenated in response', severity: 'high' } ]; await this.scanForPatterns(vulnerabilities, patterns); } async checkAccessControl(vulnerabilities) { const patterns = [ { pattern: /router\.\w+\s*\([^)]+(?!.*(?:auth|authenticate|authorize|isAuth|requireAuth))/, type: 'access_control', message: 'Route without authentication middleware', severity: 'medium' }, { pattern: /app\.\w+\s*\(\s*['"]\//, type: 'access_control', message: 'Root route without access control', severity: 'low' } ]; await this.scanForPatterns(vulnerabilities, patterns); } async checkCryptoUsage(vulnerabilities) { const patterns = [ { pattern: /crypto\.createHash\s*\(\s*['"]md5['"]\)|crypto\.createHash\s*\(\s*['"]sha1['"]\)/, type: 'weak_crypto', message: 'Weak cryptographic hash function (MD5/SHA1)', severity: 'high' }, { pattern: /Math\.random\s*\(\s*\).*(?:password|token|secret|key)/i, type: 'weak_crypto', message: 'Math.random() used for security-sensitive operations', severity: 'critical' }, { pattern: /DES|3DES|RC4/, type: 'weak_crypto', message: 'Deprecated encryption algorithm detected', severity: 'high' } ]; await this.scanForPatterns(vulnerabilities, patterns); } async scanForPatterns(vulnerabilities, patterns) { try { const files = await glob('**/*.{ts,js,jsx,tsx}', { cwd: this.projectRoot, ignore: ['node_modules/**', '.git/**', 'dist/**', 'build/**'] }); for (const file of files) { const filePath = path.join(this.projectRoot, file); try { const content = await fs.readFile(filePath, 'utf-8'); const lines = content.split('\n'); lines.forEach((line, index) => { for (const pattern of patterns) { if (pattern.pattern.test(line)) { vulnerabilities.push({ file, line: index + 1, severity: pattern.severity, type: pattern.type, message: pattern.message, recommendation: 'Follow OWASP security guidelines' }); } } }); } catch (error) { // Skip files that can't be read } } } catch (error) { // Skip if glob fails } } mapToOWASPCategory(type) { const mapping = { 'broken_access_control': 'A01:2021 - Broken Access Control', 'access_control': 'A01:2021 - Broken Access Control', 'cryptographic_failure': 'A02:2021 - Cryptographic Failures', 'weak_crypto': 'A02:2021 - Cryptographic Failures', 'hardcoded_secret': 'A02:2021 - Cryptographic Failures', 'injection': 'A03:2021 - Injection', 'sql_injection': 'A03:2021 - Injection', 'xss_injection': 'A03:2021 - Injection', 'xss': 'A03:2021 - Injection', 'insecure_design': 'A04:2021 - Insecure Design', 'csrf': 'A04:2021 - Insecure Design', 'security_misconfiguration': 'A05:2021 - Security Misconfiguration', 'missing_security_headers': 'A05:2021 - Security Misconfiguration', 'npm_vulnerability': 'A06:2021 - Vulnerable and Outdated Components', 'outdated_dependency': 'A06:2021 - Vulnerable and Outdated Components', 'known_vulnerability': 'A06:2021 - Vulnerable and Outdated Components', 'auth_failure': 'A07:2021 - Identification and Authentication Failures', 'auth_flaw': 'A07:2021 - Identification and Authentication Failures', 'session_management': 'A07:2021 - Identification and Authentication Failures', 'integrity_failure': 'A08:2021 - Software and Data Integrity Failures', 'insecure_deserialization': 'A08:2021 - Software and Data Integrity Failures', 'logging_failure': 'A09:2021 - Security Logging and Monitoring Failures', 'ssrf': 'A10:2021 - Server-Side Request Forgery (SSRF)' }; return mapping[type] || 'A04:2021 - Insecure Design'; } getImpactDescription(type, severity) { const impacts = { 'sql_injection': 'Database compromise, data theft, data manipulation', 'xss': 'Session hijacking, account takeover, defacement', 'broken_access_control': 'Unauthorized access to sensitive data or functionality', 'cryptographic_failure': 'Exposure of sensitive data, password compromise', 'ssrf': 'Internal network scanning, data exfiltration', 'insecure_deserialization': 'Remote code execution, denial of service' }; return impacts[type] || `${severity} security impact on application`; } getRemediationAdvice(type) { const remediation = { 'sql_injection': 'Use parameterized queries or prepared statements', 'xss': 'Sanitize and encode all user input before output', 'broken_access_control': 'Implement proper authentication and authorization checks', 'cryptographic_failure': 'Use strong encryption algorithms and secure key management', 'ssrf': 'Validate and sanitize URLs, use allowlists for external requests', 'csrf': 'Implement CSRF tokens for state-changing operations', 'weak_crypto': 'Use SHA-256 or stronger hash algorithms', 'hardcoded_secret': 'Move secrets to environment variables or secure vaults' }; return remediation[type] || 'Review and fix according to security best practices'; } mapToCWE(type) { const cweMapping = { 'sql_injection': 'CWE-89', 'xss': 'CWE-79', 'broken_access_control': 'CWE-284', 'cryptographic_failure': 'CWE-326', 'hardcoded_secret': 'CWE-798', 'ssrf': 'CWE-918', 'csrf': 'CWE-352', 'insecure_deserialization': 'CWE-502', 'weak_crypto': 'CWE-327' }; return cweMapping[type] || ''; } calculateCVSS(severity) { const cvssScores = { 'critical': 9.0, 'high': 7.5, 'medium': 5.0, 'low': 2.5 }; return cvssScores[severity] || 0; } getCategoryRecommendations(category, score) { const recommendations = []; if (score.score < 50) { recommendations.push(`Critical: Address ${score.critical} critical issues in ${category}`); } const categoryRecommendations = { 'A01:2021 - Broken Access Control': [ 'Implement role-based access control (RBAC)', 'Enforce access control checks on every request', 'Use secure session management' ], 'A02:2021 - Cryptographic Failures': [ 'Use strong encryption algorithms (AES-256, RSA-2048+)', 'Implement secure key management', 'Enable TLS 1.2+ for all communications' ], 'A03:2021 - Injection': [ 'Use parameterized queries for database access', 'Validate and sanitize all user input', 'Implement output encoding' ] }; if (categoryRecommendations[category] && score.issues > 0) { recommendations.push(...categoryRecommendations[category].slice(0, 2)); } return recommendations; } } //# sourceMappingURL=OWASPAnalyzer.js.map