UNPKG

mcp-siber-security-audit

Version:

MCP server for security code audit with auto-fix capabilities

146 lines (128 loc) 4.99 kB
#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const ESLintScanner = require('./src/scanners/eslint-scanner'); const SecretScanner = require('./src/scanners/secret-scanner'); const SemgrepScanner = require('./src/scanners/semgrep-scanner'); const DependencyScanner = require('./src/scanners/dependency-scanner'); const InsecureURLFixer = require('./src/fixers/common-fixes'); const ESLintFixer = require('./src/fixers/eslint-fixer'); const XSSFixer = require('./src/fixers/xss-fixer'); const SQLInjectionFixer = require('./src/fixers/sql-injection-fixer'); const SecretFixer = require('./src/fixers/secret-fixer'); const ReportGenerator = require('./src/utils/report-generator'); class SecurityAuditor { constructor() { this.scanners = [ new ESLintScanner(), new SecretScanner(), new SemgrepScanner(), new DependencyScanner(), ]; this.fixers = { 'HARDCODED_API_KEY': new SecretFixer(), 'INSECURE_URL': new SecretFixer(), 'SRC.CONFIG.EXPRESS_XSS': new XSSFixer(), 'SRC.CONFIG.EXPRESS_SQL_INJECTION': new SQLInjectionFixer(), }; } async scan(directory) { const issues = []; const files = this._getAllFiles(directory); for (const file of files) { for (const scanner of this.scanners) { const results = await scanner.scanFile(file); issues.push(...results); } } return issues; } async fix(issues) { for (const issue of issues) { const fixer = this.fixers[issue.type]; if (fixer) { const fileContent = fs.readFileSync(issue.file, 'utf-8'); const { fixedContent, isFixed } = fixer.applyFix(fileContent, issue); if (isFixed) { fs.writeFileSync(issue.file, fixedContent); console.log(`Fixed: ${issue.description} in ${issue.file}`); } } } } _getAllFiles(dir) { try { let files = []; // Normalize path to handle . and .. correctly const normalizedDir = path.resolve(dir); // Check if directory exists if (!fs.existsSync(normalizedDir)) { console.error(`Error: Directory "${dir}" does not exist.`); console.error('Usage: mcp-siber-security-audit <directory> [--fix]'); console.error('Example: '); console.error(' mcp-siber-security-audit .'); console.error(' mcp-siber-security-audit my-project'); process.exit(1); } const entries = fs.readdirSync(normalizedDir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(normalizedDir, entry.name); if (entry.isDirectory()) { if (entry.name === 'node_modules') continue; files = files.concat(this._getAllFiles(fullPath)); } else { if (path.extname(entry.name) === '.js' || entry.name === 'package.json') { files.push(fullPath); } } } return files; } catch (error) { console.error(`Error scanning directory: ${error.message}`); process.exit(1); } } async run() { const args = process.argv.slice(2); const directory = args[0]; const shouldFix = args.includes('--fix'); const shouldGenerateReport = args.includes('--report'); const reportDir = args.find(arg => arg.startsWith('--report-dir='))?.split('=')?.[1] || 'security-reports'; if (!directory) { console.error('Usage: mcp-siber-security-audit <directory> [--fix] [--report] [--report-dir=path]'); console.error('Options:'); console.error(' --fix Automatically fix detected issues when possible'); console.error(' --report Generate detailed reports (JSON, Markdown, and HTML)'); console.error(' --report-dir=path Specify output directory for reports (default: security-reports)'); process.exit(1); } const issues = await this.scan(directory); // Always show summary in console console.log('\nSecurity Scan Results:'); const severityCounts = issues.reduce((acc, issue) => { acc[issue.severity] = (acc[issue.severity] || 0) + 1; return acc; }, {}); console.log('\nIssues found by severity:'); Object.entries(severityCounts).forEach(([severity, count]) => { console.log(`${severity.toUpperCase()}: ${count}`); }); // Generate report const reporter = new ReportGenerator(); reporter.addIssues(issues); if (shouldGenerateReport) { const reportPaths = reporter.saveReport(reportDir); console.log(`\nReport saved to: ${reportPaths.jsonPath}`); } else { // If no report requested, show structured output in console console.log(JSON.stringify(reporter.report, null, 2)); } if (shouldFix) { console.log('\nApplying fixes...'); await this.fix(issues); console.log('Fixes applied.'); } } } const auditor = new SecurityAuditor(); auditor.run().catch(error => console.error(error));