mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
557 lines • 23.8 kB
JavaScript
/**
* 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