UNPKG

mcp-siber-security-audit

Version:

MCP server for security code audit with auto-fix capabilities

125 lines (114 loc) 3.99 kB
const { ESLint } = require('eslint'); const path = require('path'); const fs = require('fs'); class ESLintScanner { constructor() { // Get the path to our package's node_modules const packageRoot = path.dirname(require.resolve('../../package.json')); const pluginPath = path.join(packageRoot, 'node_modules', 'eslint-plugin-security'); this.eslint = new ESLint({ resolvePluginsRelativeTo: packageRoot, useEslintrc: false, overrideConfigFile: null, overrideConfig: { parserOptions: { ecmaVersion: 2021, sourceType: 'module', }, plugins: ['security'], rules: { 'security/detect-buffer-noassert': 'error', 'security/detect-child-process': 'error', 'security/detect-disable-mustache-escape': 'error', 'security/detect-eval-with-expression': 'error', 'security/detect-new-buffer': 'error', 'security/detect-no-csrf-before-method-override': 'error', 'security/detect-non-literal-fs-filename': 'error', 'security/detect-non-literal-regexp': 'error', 'security/detect-non-literal-require': 'error', 'security/detect-object-injection': 'error', 'security/detect-possible-timing-attacks': 'error', 'security/detect-pseudoRandomBytes': 'error', 'security/detect-unsafe-regex': 'error', 'security/detect-bidi-characters': 'error', 'no-eval': 'error', }, }, }); } async scanFile(filePath) { const results = await this.eslint.lintFiles([filePath]); return this.formatResults(results, filePath); } formatResults(results, filePath) { // Use Map to group similar issues const issueGroups = new Map(); for (const result of results) { for (const message of result.messages) { const type = this.mapRuleToType(message.ruleId); const description = message.message; // Create a key that uniquely identifies similar issues const key = `${type}:${description}:${filePath}`; if (!issueGroups.has(key)) { issueGroups.set(key, { scanner: 'eslint', file: filePath, locations: [], type: type, severity: this.mapSeverity(message.severity), description: description, ruleId: message.ruleId, auto_fix_available: false }); } // Add location to the group issueGroups.get(key).locations.push({ line: message.line, column: message.column }); } } // Convert grouped issues to final format return Array.from(issueGroups.values()).map(issue => { if (issue.locations.length === 1) { // If only one location, use the original format return { ...issue, line: issue.locations[0].line, column: issue.locations[0].column, locations: undefined }; } else { // If multiple locations, include first one in main fields and list all in locations return { ...issue, line: issue.locations[0].line, column: issue.locations[0].column, description: `${issue.description} (Found in ${issue.locations.length} locations)` }; } }); } mapRuleToType(ruleId) { if (!ruleId) { return 'LINT_ERROR'; } if (ruleId.includes('sql-injection')) return 'SQL_INJECTION'; if (ruleId.includes('xss')) return 'XSS'; if (ruleId.startsWith('security/')) { return ruleId.replace('security/', '').toUpperCase().replace(/-/g, '_'); } if (ruleId === 'no-eval') { return 'CODE_EXECUTION'; } return 'UNKNOWN'; } mapSeverity(eslintSeverity) { switch (eslintSeverity) { case 2: return 'high'; case 1: return 'medium'; default: return 'low'; } } } module.exports = ESLintScanner;