Skip to main content
Glama
security-analyzer.ts5.27 kB
import type { CodeFile, SecurityIssue } from '../types/index.js'; import { FileReader } from '../utils/file-reader.js'; export class SecurityAnalyzer { /** * Scan code for security issues */ async scanSecurityIssues(files: CodeFile[] | string[]): Promise<SecurityIssue[]> { const codeFiles = await this.getCodeFiles(files); const issues: SecurityIssue[] = []; for (const file of codeFiles) { // Detect hardcoded secrets issues.push(...this.detectSecrets(file)); // Detect weak authentication issues.push(...this.detectWeakAuth(file)); // Detect insecure dependencies (would check package.json in real implementation) // Detect permission issues issues.push(...this.detectPermissionIssues(file)); } return issues; } /** * Detect hardcoded secrets in code */ private detectSecrets(file: CodeFile): SecurityIssue[] { const issues: SecurityIssue[] = []; const lines = file.content.split('\n'); // Common secret patterns const secretPatterns = [ { pattern: /(?:password|passwd|pwd)\s*[=:]\s*["']([^"']+)["']/gi, type: 'password' as const, severity: 'critical' as const, }, { pattern: /(?:api[_-]?key|apikey)\s*[=:]\s*["']([^"']+)["']/gi, type: 'api_key' as const, severity: 'critical' as const, }, { pattern: /(?:secret|token)\s*[=:]\s*["']([^"']+)["']/gi, type: 'secret' as const, severity: 'high' as const, }, { pattern: /(?:aws[_-]?access[_-]?key|aws[_-]?secret)\s*[=:]\s*["']([^"']+)["']/gi, type: 'aws_credentials' as const, severity: 'critical' as const, }, { pattern: /(?:private[_-]?key|ssh[_-]?key)\s*[=:]\s*["']([^"']+)["']/gi, type: 'private_key' as const, severity: 'critical' as const, }, ]; for (let i = 0; i < lines.length; i++) { const line = lines[i]; for (const { pattern, type, severity } of secretPatterns) { if (pattern.test(line)) { issues.push({ type: 'secret', severity, location: `${file.path}:${i + 1}`, description: `Potential hardcoded ${type} detected`, recommendation: 'Move secrets to environment variables or secure configuration', detectedAt: new Date(), }); } } } return issues; } /** * Detect weak authentication patterns */ private detectWeakAuth(file: CodeFile): SecurityIssue[] { const issues: SecurityIssue[] = []; const content = file.content.toLowerCase(); // Weak password validation if (content.includes('password.length') && !content.includes('password.length >= 8')) { issues.push({ type: 'weak_auth', severity: 'medium', location: file.path, description: 'Weak password validation detected', recommendation: 'Enforce minimum password length and complexity requirements', detectedAt: new Date(), }); } // SQL injection vulnerabilities if (content.includes('query') && content.includes('+') && !content.includes('parameterized')) { const sqlKeywords = ['select', 'insert', 'update', 'delete']; if (sqlKeywords.some((keyword) => content.includes(keyword))) { issues.push({ type: 'other', severity: 'high', location: file.path, description: 'Potential SQL injection vulnerability', recommendation: 'Use parameterized queries or prepared statements', detectedAt: new Date(), }); } } // XSS vulnerabilities if (content.includes('innerhtml') || content.includes('document.write')) { issues.push({ type: 'other', severity: 'high', location: file.path, description: 'Potential XSS vulnerability', recommendation: 'Use textContent or sanitize HTML input', detectedAt: new Date(), }); } return issues; } /** * Detect permission issues */ private detectPermissionIssues(file: CodeFile): SecurityIssue[] { const issues: SecurityIssue[] = []; const content = file.content.toLowerCase(); // File system operations without permission checks if (content.includes('fs.writefile') || content.includes('fs.unlink')) { if (!content.includes('permission') && !content.includes('access')) { issues.push({ type: 'permission', severity: 'medium', location: file.path, description: 'File system operations without permission checks', recommendation: 'Add permission checks before file operations', detectedAt: new Date(), }); } } return issues; } /** * Get code files from paths or CodeFile objects */ private async getCodeFiles(files: CodeFile[] | string[]): Promise<CodeFile[]> { if (files.length === 0) return []; if (typeof files[0] === 'string') { return await FileReader.readFiles((files as string[]).join(','), { ignore: ['node_modules/**', 'dist/**', 'build/**'], }); } return files as CodeFile[]; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/code-alchemist01/development-tools-mcp-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server