import { SecurityScannerPort, SecurityScanOptions } from '../../domain/ports/SecurityScannerPort'; import { SecurityIssue, SecurityIssueImpl } from '../../domain/entities/SecurityIssue'; import { CodeBlock } from '../../domain/entities/CodeBlock'; import { LLMPort } from '../../domain/ports/LLMPort'; export class SecurityScannerAdapter implements SecurityScannerPort { constructor(private readonly llmPort: LLMPort) {} async scanCodeBlocks( codeBlocks: CodeBlock[], options: SecurityScanOptions ): Promise { const allIssues: SecurityIssue[] = []; for (const codeBlock of codeBlocks) { const issues = await this.scanCodeBlock(codeBlock, options); allIssues.push(...issues); } return allIssues; } async scanCodeBlock( codeBlock: CodeBlock, options: SecurityScanOptions ): Promise { try { const prompt = this.createSecurityScanPrompt(codeBlock, options); const messages = [ { role: 'system' as const, content: 'You are a cybersecurity expert. Analyze code for security vulnerabilities, insecure patterns, and potential attack vectors. Focus on common security issues like injection attacks, authentication bypasses, data exposure, and unsafe coding practices.', }, { role: 'user' as const, content: prompt, }, ]; const response = await this.llmPort.generateResponse(messages, { temperature: 0.2, maxTokens: 2500, }); return this.parseSecurityIssues(response.content, codeBlock); } catch (error) { return []; } } async scanDependencies( packageJsonPath: string, lockFilePath?: string ): Promise> { // This is a simplified implementation // In a real implementation, you'd integrate with vulnerability databases // like npm audit, Snyk, or OWASP Dependency Check try { const fs = await import('fs/promises'); const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8')); const vulnerabilities: Array<{ readonly packageName: string; readonly version: string; readonly severity: 'low' | 'medium' | 'high' | 'critical'; readonly cve?: string; readonly description: string; readonly fixedVersion?: string; readonly references: string[]; }> = []; // Mock some vulnerabilities for demonstration const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies }; for (const [name, version] of Object.entries(dependencies)) { // Simulate finding vulnerabilities in some packages if (name.includes('lodash') && Math.random() > 0.7) { vulnerabilities.push({ packageName: name, version: version as string, severity: 'medium', cve: 'CVE-2021-23337', description: 'Command injection vulnerability in lodash', fixedVersion: '4.17.21', references: ['https://nvd.nist.gov/vuln/detail/CVE-2021-23337'], }); } } return vulnerabilities; } catch (error) { return []; } } async scanForSecrets(codeBlocks: CodeBlock[]): Promise { const issues: SecurityIssue[] = []; for (const codeBlock of codeBlocks) { // Use both pattern-based detection and LLM-based detection const patternBasedSecrets = this.detectSecrets(codeBlock); const llmBasedSecrets = await this.detectSecretsWithLLM(codeBlock); issues.push(...patternBasedSecrets); issues.push(...llmBasedSecrets); } // Remove duplicates based on file path and line number return this.deduplicateIssues(issues); } private async detectSecretsWithLLM(codeBlock: CodeBlock): Promise { try { const prompt = ` Analyze this ${codeBlock.language} code specifically for exposed secrets, API keys, passwords, and sensitive credentials: File: ${codeBlock.filePath} Lines: ${codeBlock.startLine}-${codeBlock.endLine} Code: \`\`\`${codeBlock.language} ${codeBlock.content} \`\`\` Look for: 1. API keys (OpenAI, Google, AWS, Azure, Stripe, etc.) 2. Database passwords and connection strings 3. JWT secrets and encryption keys 4. OAuth client secrets 5. Private keys and certificates 6. High-entropy strings that could be secrets 7. Hardcoded credentials in any form Return findings in JSON format: [ { "severity": "critical|high|medium|low", "category": "secret_exposure", "title": "Exposed Secret: [Type]", "description": "Detailed description of the exposed secret and its risk", "lineNumber": 42, "remediation": "Specific steps to secure this secret", "references": ["https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_credentials"], "secretType": "API_KEY|PASSWORD|TOKEN|PRIVATE_KEY|DATABASE_URL|etc" } ] `; const messages = [ { role: 'system' as const, content: 'You are a cybersecurity expert specializing in secret detection and credential security. Your job is to identify any exposed secrets, API keys, passwords, or sensitive credentials in code. Be thorough but accurate - only flag actual secrets, not placeholder values or examples.', }, { role: 'user' as const, content: prompt, }, ]; const response = await this.llmPort.generateResponse(messages, { temperature: 0.1, // Low temperature for consistent secret detection maxTokens: 2000, }); return this.parseSecurityIssues(response.content, codeBlock); } catch (error) { return []; } } private deduplicateIssues(issues: SecurityIssue[]): SecurityIssue[] { const seen = new Set(); return issues.filter(issue => { const key = `${issue.filePath}:${issue.lineNumber}:${issue.title}`; if (seen.has(key)) { return false; } seen.add(key); return true; }); } async scanForInsecurePatterns(codeBlocks: CodeBlock[]): Promise { const issues: SecurityIssue[] = []; for (const codeBlock of codeBlocks) { const patterns = this.detectInsecurePatterns(codeBlock); issues.push(...patterns); } return issues; } async validateSecurityConfig(configFiles: CodeBlock[]): Promise { const issues: SecurityIssue[] = []; for (const configFile of configFiles) { const configIssues = this.analyzeSecurityConfig(configFile); issues.push(...configIssues); } return issues; } async getSecurityBestPractices(language: string): Promise { const bestPractices: Record = { javascript: [ 'Use Content Security Policy (CSP) headers', 'Validate and sanitize all user inputs', 'Use parameterized queries to prevent SQL injection', 'Implement proper authentication and authorization', 'Use HTTPS for all communications', 'Regularly update dependencies', 'Implement rate limiting', 'Use secure session management', 'Encrypt sensitive data at rest and in transit', 'Implement proper error handling without information disclosure', ], python: [ 'Use parameterized queries to prevent SQL injection', 'Validate and sanitize all user inputs', 'Use secure random number generators', 'Implement proper authentication and authorization', 'Use HTTPS for all communications', 'Regularly update dependencies', 'Implement rate limiting', 'Use secure session management', 'Encrypt sensitive data at rest and in transit', 'Implement proper error handling without information disclosure', ], java: [ 'Use parameterized queries to prevent SQL injection', 'Validate and sanitize all user inputs', 'Use secure random number generators', 'Implement proper authentication and authorization', 'Use HTTPS for all communications', 'Regularly update dependencies', 'Implement rate limiting', 'Use secure session management', 'Encrypt sensitive data at rest and in transit', 'Implement proper error handling without information disclosure', ], typescript: [ 'Use Content Security Policy (CSP) headers', 'Validate and sanitize all user inputs', 'Use parameterized queries to prevent SQL injection', 'Implement proper authentication and authorization', 'Use HTTPS for all communications', 'Regularly update dependencies', 'Implement rate limiting', 'Use secure session management', 'Encrypt sensitive data at rest and in transit', 'Implement proper error handling without information disclosure', ], }; return (bestPractices[language.toLowerCase()] || bestPractices.javascript) as string[]; } async checkCVE(pattern: string, language: string): Promise<{ readonly cveId?: string; readonly severity?: 'low' | 'medium' | 'high' | 'critical'; readonly description?: string; }> { // This is a simplified implementation // In a real implementation, you'd query CVE databases const knownPatterns: Record = { 'eval(': { cveId: 'CVE-2021-23337', severity: 'high', description: 'Code injection vulnerability through eval() function', }, 'innerHTML': { cveId: 'CVE-2021-23338', severity: 'medium', description: 'Cross-site scripting (XSS) vulnerability', }, 'document.write': { cveId: 'CVE-2021-23339', severity: 'medium', description: 'Cross-site scripting (XSS) vulnerability', }, }; return knownPatterns[pattern] || {}; } private createSecurityScanPrompt(codeBlock: CodeBlock, options: SecurityScanOptions): string { return ` Analyze the following ${codeBlock.language} code for security vulnerabilities and exposed secrets: File: ${codeBlock.filePath} Lines: ${codeBlock.startLine}-${codeBlock.endLine} Code: \`\`\`${codeBlock.language} ${codeBlock.content} \`\`\` Focus on these categories: ${options.categories.join(', ')} Minimum severity: ${options.severity.join(', ')} CRITICAL: Pay special attention to exposed secrets and credentials. Look for: SECRETS AND CREDENTIALS: 1. Hardcoded API keys (OpenAI, Google, AWS, Azure, etc.) 2. Database passwords and connection strings 3. JWT secrets and encryption keys 4. OAuth client secrets 5. Payment processing keys (Stripe, PayPal, Square) 6. Social media tokens (GitHub, Slack, Discord, etc.) 7. Cloud provider credentials (AWS, Azure, GCP) 8. High-entropy strings that could be secrets 9. Email addresses with potential passwords 10. Private keys and certificates SECURITY VULNERABILITIES: 1. Injection vulnerabilities (SQL, NoSQL, Command, LDAP, etc.) 2. Authentication and authorization issues 3. Cryptographic weaknesses 4. Data exposure and leakage 5. Input validation problems 6. Unsafe deserialization 7. Cross-site scripting (XSS) 8. Cross-site request forgery (CSRF) 9. Insecure direct object references 10. Security misconfiguration 11. Insecure random number generation 12. Weak hashing algorithms (MD5, SHA1) 13. Hardcoded secrets in configuration files For each secret found, provide: - Exact location and line number - Type of secret (API key, password, token, etc.) - Risk assessment and potential impact - Specific remediation steps Provide findings in JSON format: [ { "severity": "low|medium|high|critical", "category": "injection|authentication|authorization|cryptography|data_exposure|input_validation|dependency|configuration|logging|secret_exposure|other", "title": "Brief title of the issue", "description": "Detailed description of the vulnerability or exposed secret", "lineNumber": 42, "remediation": "Specific steps to fix this issue", "references": ["URL1", "URL2"], "secretType": "API_KEY|PASSWORD|TOKEN|PRIVATE_KEY|etc" // Only for secrets } ] `; } private parseSecurityIssues(response: string, codeBlock: CodeBlock): SecurityIssue[] { try { const parsed = JSON.parse(response); if (Array.isArray(parsed)) { return parsed.map(item => { const issue = new SecurityIssueImpl() .id(`security-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`) .severity(item.severity) .category(item.category) .title(item.title) .description(item.description) .filePath(codeBlock.filePath) .remediation(item.remediation); if (item.lineNumber) { issue.lineNumber(item.lineNumber); } if (item.references && Array.isArray(item.references)) { issue.references(item.references); } return issue.build(); }); } } catch (error) { // If JSON parsing fails, create a basic security issue const issue = new SecurityIssueImpl() .id(`security-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`) .severity('medium') .category('other') .title('Security Analysis') .description(response) .filePath(codeBlock.filePath) .remediation('Review the analysis above for security concerns') .build(); return [issue]; } return []; } private detectSecrets(codeBlock: CodeBlock): SecurityIssue[] { const issues: SecurityIssue[] = []; const lines = codeBlock.content.split('\n'); // Enhanced secret detection patterns const secretPatterns = [ // API Keys and Tokens { pattern: /api[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'API Key', severity: 'high' as const, description: 'Hardcoded API key detected' }, { pattern: /secret\s*[:=]\s*['"][^'"]+['"]/i, type: 'Secret', severity: 'high' as const, description: 'Hardcoded secret detected' }, { pattern: /password\s*[:=]\s*['"][^'"]+['"]/i, type: 'Password', severity: 'critical' as const, description: 'Hardcoded password detected' }, { pattern: /token\s*[:=]\s*['"][^'"]+['"]/i, type: 'Token', severity: 'high' as const, description: 'Hardcoded token detected' }, // Cloud Provider Keys { pattern: /aws[_-]?access[_-]?key[_-]?id\s*[:=]\s*['"][^'"]+['"]/i, type: 'AWS Access Key ID', severity: 'critical' as const, description: 'AWS Access Key ID exposed' }, { pattern: /aws[_-]?secret[_-]?access[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'AWS Secret Access Key', severity: 'critical' as const, description: 'AWS Secret Access Key exposed' }, { pattern: /aws[_-]?session[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'AWS Session Token', severity: 'critical' as const, description: 'AWS Session Token exposed' }, { pattern: /azure[_-]?subscription[_-]?id\s*[:=]\s*['"][^'"]+['"]/i, type: 'Azure Subscription ID', severity: 'high' as const, description: 'Azure Subscription ID exposed' }, { pattern: /azure[_-]?client[_-]?secret\s*[:=]\s*['"][^'"]+['"]/i, type: 'Azure Client Secret', severity: 'critical' as const, description: 'Azure Client Secret exposed' }, { pattern: /google[_-]?api[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'Google API Key', severity: 'high' as const, description: 'Google API Key exposed' }, { pattern: /firebase[_-]?api[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'Firebase API Key', severity: 'high' as const, description: 'Firebase API Key exposed' }, // Service-specific Tokens { pattern: /github[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'GitHub Token', severity: 'high' as const, description: 'GitHub Token exposed' }, { pattern: /gitlab[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'GitLab Token', severity: 'high' as const, description: 'GitLab Token exposed' }, { pattern: /bitbucket[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'Bitbucket Token', severity: 'high' as const, description: 'Bitbucket Token exposed' }, { pattern: /slack[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'Slack Token', severity: 'high' as const, description: 'Slack Token exposed' }, { pattern: /discord[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'Discord Token', severity: 'high' as const, description: 'Discord Token exposed' }, { pattern: /telegram[_-]?bot[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'Telegram Bot Token', severity: 'high' as const, description: 'Telegram Bot Token exposed' }, // Database Credentials { pattern: /database[_-]?password\s*[:=]\s*['"][^'"]+['"]/i, type: 'Database Password', severity: 'critical' as const, description: 'Database password exposed' }, { pattern: /db[_-]?password\s*[:=]\s*['"][^'"]+['"]/i, type: 'Database Password', severity: 'critical' as const, description: 'Database password exposed' }, { pattern: /mongodb[_-]?uri\s*[:=]\s*['"][^'"]+['"]/i, type: 'MongoDB URI', severity: 'high' as const, description: 'MongoDB connection string with credentials exposed' }, { pattern: /postgres[_-]?url\s*[:=]\s*['"][^'"]+['"]/i, type: 'PostgreSQL URL', severity: 'high' as const, description: 'PostgreSQL connection string with credentials exposed' }, // JWT and Crypto Keys { pattern: /jwt[_-]?secret\s*[:=]\s*['"][^'"]+['"]/i, type: 'JWT Secret', severity: 'critical' as const, description: 'JWT Secret exposed' }, { pattern: /private[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'Private Key', severity: 'critical' as const, description: 'Private key exposed' }, { pattern: /public[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'Public Key', severity: 'medium' as const, description: 'Public key exposed (may contain sensitive information)' }, { pattern: /encryption[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'Encryption Key', severity: 'critical' as const, description: 'Encryption key exposed' }, // OAuth and Social Media { pattern: /oauth[_-]?client[_-]?secret\s*[:=]\s*['"][^'"]+['"]/i, type: 'OAuth Client Secret', severity: 'critical' as const, description: 'OAuth Client Secret exposed' }, { pattern: /facebook[_-]?app[_-]?secret\s*[:=]\s*['"][^'"]+['"]/i, type: 'Facebook App Secret', severity: 'high' as const, description: 'Facebook App Secret exposed' }, { pattern: /twitter[_-]?api[_-]?secret\s*[:=]\s*['"][^'"]+['"]/i, type: 'Twitter API Secret', severity: 'high' as const, description: 'Twitter API Secret exposed' }, { pattern: /instagram[_-]?access[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'Instagram Access Token', severity: 'high' as const, description: 'Instagram Access Token exposed' }, // Payment and Financial { pattern: /stripe[_-]?secret[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'Stripe Secret Key', severity: 'critical' as const, description: 'Stripe Secret Key exposed' }, { pattern: /paypal[_-]?client[_-]?secret\s*[:=]\s*['"][^'"]+['"]/i, type: 'PayPal Client Secret', severity: 'critical' as const, description: 'PayPal Client Secret exposed' }, { pattern: /square[_-]?access[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'Square Access Token', severity: 'high' as const, description: 'Square Access Token exposed' }, // AI and ML Services { pattern: /openai[_-]?api[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'OpenAI API Key', severity: 'high' as const, description: 'OpenAI API Key exposed' }, { pattern: /anthropic[_-]?api[_-]?key\s*[:=]\s*['"][^'"]+['"]/i, type: 'Anthropic API Key', severity: 'high' as const, description: 'Anthropic API Key exposed' }, { pattern: /huggingface[_-]?token\s*[:=]\s*['"][^'"]+['"]/i, type: 'Hugging Face Token', severity: 'high' as const, description: 'Hugging Face Token exposed' }, // Generic patterns for high-entropy strings (potential secrets) { pattern: /['"][a-zA-Z0-9+/]{40,}['"]/g, type: 'Potential Secret', severity: 'medium' as const, description: 'High-entropy string detected (possible secret)', validate: this.validateHighEntropyString }, // Email addresses that might be test accounts with passwords { pattern: /email\s*[:=]\s*['"][^'"]+@[^'"]+\.[^'"]+['"]/i, type: 'Email Address', severity: 'low' as const, description: 'Email address in code (may be test account)' }, ]; for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (!line) continue; for (const { pattern, type, severity, description, validate } of secretPatterns) { const matches = line.match(pattern); if (matches) { // Skip if this is a validation pattern and validation fails if (validate && !validate(matches[0])) { continue; } const issue = new SecurityIssueImpl() .id(`secret-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`) .severity(severity) .category('data_exposure') .title(description) .description(`${description}. Found in ${codeBlock.filePath} at line ${codeBlock.startLine + i}. This exposes sensitive credentials that should never be hardcoded in source code.`) .filePath(codeBlock.filePath) .lineNumber(codeBlock.startLine + i) .codeSnippet(line.trim()) .remediation(this.getSecretRemediation(type)) .addReference('https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_credentials') .addReference('https://github.com/Yelp/detect-secrets') .addReference('https://docs.github.com/en/code-security/secret-scanning') .build(); issues.push(issue); } } } return issues; } private validateHighEntropyString(match: string): boolean { // Remove quotes and check if it's a high-entropy string const cleanMatch = match.replace(/['"]/g, ''); // Check for base64-like patterns if (/^[A-Za-z0-9+/]+=*$/.test(cleanMatch) && cleanMatch.length >= 40) { return true; } // Check for hex-like patterns if (/^[A-Fa-f0-9]+$/.test(cleanMatch) && cleanMatch.length >= 32) { return true; } return false; } private getSecretRemediation(secretType: string): string { const remediationMap: Record = { 'API Key': 'Use environment variables (e.g., process.env.API_KEY) or secure configuration management services like AWS Secrets Manager, Azure Key Vault, or HashiCorp Vault.', 'Secret': 'Store secrets in environment variables or secure configuration management. Never commit secrets to version control.', 'Password': 'Use environment variables for passwords. Consider using OAuth, JWT tokens, or other secure authentication methods.', 'Token': 'Store tokens in environment variables or secure token management systems. Implement token rotation and expiration.', 'AWS Access Key ID': 'Use AWS IAM roles, environment variables, or AWS Secrets Manager. Never commit AWS credentials to version control.', 'AWS Secret Access Key': 'Use AWS IAM roles, environment variables, or AWS Secrets Manager. Rotate credentials regularly.', 'AWS Session Token': 'Use temporary credentials with IAM roles. Session tokens should not be hardcoded.', 'Database Password': 'Use environment variables or connection string builders. Consider using managed database services with IAM authentication.', 'JWT Secret': 'Use a strong, randomly generated secret stored in environment variables. Consider using RS256 with proper key management.', 'Private Key': 'Store private keys in secure key management systems. Use environment variables or encrypted configuration files.', 'OAuth Client Secret': 'Store OAuth secrets in environment variables or secure configuration management. Never expose in client-side code.', 'Stripe Secret Key': 'Use environment variables for Stripe keys. Implement webhook signature verification for additional security.', 'OpenAI API Key': 'Store API keys in environment variables. Implement usage monitoring and rate limiting.', 'Potential Secret': 'Verify if this is actually a secret. If so, move to environment variables or secure configuration management.', 'Email Address': 'If this is a test account, use environment variables. Avoid using real email addresses in test code.' }; return remediationMap[secretType] || 'Remove hardcoded secrets and use environment variables or secure configuration management instead.'; } private detectInsecurePatterns(codeBlock: CodeBlock): SecurityIssue[] { const issues: SecurityIssue[] = []; const lines = codeBlock.content.split('\n'); const insecurePatterns = [ { pattern: /eval\s*\(/i, type: 'Code Injection', severity: 'high' as const, category: 'injection' as const }, { pattern: /innerHTML\s*=/i, type: 'XSS Vulnerability', severity: 'medium' as const, category: 'input_validation' as const }, { pattern: /document\.write\s*\(/i, type: 'XSS Vulnerability', severity: 'medium' as const, category: 'input_validation' as const }, { pattern: /dangerouslySetInnerHTML/i, type: 'XSS Vulnerability', severity: 'medium' as const, category: 'input_validation' as const }, { pattern: /exec\s*\(/i, type: 'Command Injection', severity: 'high' as const, category: 'injection' as const }, { pattern: /system\s*\(/i, type: 'Command Injection', severity: 'high' as const, category: 'injection' as const }, { pattern: /shell_exec\s*\(/i, type: 'Command Injection', severity: 'high' as const, category: 'injection' as const }, { pattern: /md5\s*\(/i, type: 'Weak Cryptography', severity: 'medium' as const, category: 'cryptography' as const }, { pattern: /sha1\s*\(/i, type: 'Weak Cryptography', severity: 'medium' as const, category: 'cryptography' as const }, { pattern: /Math\.random\s*\(/i, type: 'Insecure Random', severity: 'medium' as const, category: 'cryptography' as const }, ]; for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (!line) continue; for (const { pattern, type, severity, category } of insecurePatterns) { if (pattern.test(line)) { const issue = new SecurityIssueImpl() .id(`pattern-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`) .severity(severity) .category(category) .title(`Insecure Pattern: ${type}`) .description(`An insecure pattern '${pattern.source}' was detected. This can lead to security vulnerabilities.`) .filePath(codeBlock.filePath) .lineNumber(codeBlock.startLine + i) .codeSnippet(line.trim()) .remediation(`Replace the insecure pattern with a secure alternative. Consider using safer APIs or libraries.`) .build(); issues.push(issue); } } } return issues; } private analyzeSecurityConfig(configFile: CodeBlock): SecurityIssue[] { const issues: SecurityIssue[] = []; const content = configFile.content.toLowerCase(); // Check for common security misconfigurations if (content.includes('debug: true') || content.includes('debug=true')) { const issue = new SecurityIssueImpl() .id(`config-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`) .severity('medium') .category('configuration') .title('Debug Mode Enabled') .description('Debug mode is enabled in configuration. This can expose sensitive information in production.') .filePath(configFile.filePath) .remediation('Disable debug mode in production environments.') .build(); issues.push(issue); } if (content.includes('cors:') && !content.includes('origin')) { const issue = new SecurityIssueImpl() .id(`config-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`) .severity('medium') .category('configuration') .title('CORS Misconfiguration') .description('CORS is configured but origin is not properly restricted.') .filePath(configFile.filePath) .remediation('Configure CORS to only allow specific origins.') .build(); issues.push(issue); } return issues; } }