agent-security-scanner-mcp 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/utils.js ADDED
@@ -0,0 +1,153 @@
1
+ import { execFileSync } from "child_process";
2
+ import { readFileSync, existsSync } from "fs";
3
+ import { dirname, join, extname, basename } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { FIX_TEMPLATES } from './fix-patterns.js';
6
+
7
+ // Handle both ESM and CJS bundling (Smithery bundles to CJS)
8
+ let __dirname;
9
+ try {
10
+ __dirname = dirname(fileURLToPath(import.meta.url));
11
+ } catch {
12
+ __dirname = process.cwd();
13
+ }
14
+
15
+ // Detect language from file extension
16
+ export function detectLanguage(filePath) {
17
+ // Check basename first for extensionless files like Dockerfile
18
+ const base = filePath.split('/').pop().split('\\').pop().toLowerCase();
19
+ if (base === 'dockerfile' || base.startsWith('dockerfile.')) return 'dockerfile';
20
+
21
+ const ext = filePath.split('.').pop().toLowerCase();
22
+ const langMap = {
23
+ 'py': 'python', 'js': 'javascript', 'ts': 'typescript',
24
+ 'tsx': 'typescript', 'jsx': 'javascript', 'java': 'java',
25
+ 'go': 'go', 'rb': 'ruby', 'php': 'php',
26
+ 'cs': 'csharp', 'rs': 'rust', 'c': 'c', 'cpp': 'cpp',
27
+ 'cc': 'cpp', 'cxx': 'cpp', 'h': 'c', 'hpp': 'cpp',
28
+ 'tf': 'terraform', 'hcl': 'terraform',
29
+ 'yaml': 'generic', 'yml': 'generic',
30
+ 'sql': 'sql',
31
+ // Prompt/text file extensions for prompt injection scanning
32
+ 'txt': 'generic', 'md': 'generic', 'prompt': 'generic',
33
+ 'jinja': 'generic', 'jinja2': 'generic', 'j2': 'generic'
34
+ };
35
+ return langMap[ext] || 'generic';
36
+ }
37
+
38
+ // Run the Python analyzer
39
+ export function runAnalyzer(filePath) {
40
+ try {
41
+ const analyzerPath = join(__dirname, '..', 'analyzer.py');
42
+ const result = execFileSync('python3', [analyzerPath, filePath], {
43
+ encoding: 'utf-8',
44
+ timeout: 30000
45
+ });
46
+ return JSON.parse(result);
47
+ } catch (error) {
48
+ return { error: error.message };
49
+ }
50
+ }
51
+
52
+ // Generate fix suggestion for an issue
53
+ export function generateFix(issue, line, language) {
54
+ const ruleId = issue.ruleId.toLowerCase();
55
+
56
+ for (const [pattern, template] of Object.entries(FIX_TEMPLATES)) {
57
+ if (ruleId.includes(pattern)) {
58
+ return {
59
+ description: template.description,
60
+ original: line,
61
+ fixed: template.fix(line, language)
62
+ };
63
+ }
64
+ }
65
+
66
+ return {
67
+ description: "Review and fix manually based on the security rule",
68
+ original: line,
69
+ fixed: null
70
+ };
71
+ }
72
+
73
+ // Convert issues to SARIF 2.1.0 format
74
+ export function toSarif(file_path, language, issues) {
75
+ const severityToLevel = {
76
+ 'error': 'error',
77
+ 'ERROR': 'error',
78
+ 'warning': 'warning',
79
+ 'WARNING': 'warning',
80
+ 'info': 'note',
81
+ 'INFO': 'note'
82
+ };
83
+
84
+ // Build unique rules from issues
85
+ const rulesMap = new Map();
86
+ for (const issue of issues) {
87
+ if (!rulesMap.has(issue.ruleId)) {
88
+ rulesMap.set(issue.ruleId, {
89
+ id: issue.ruleId,
90
+ shortDescription: { text: issue.message },
91
+ defaultConfiguration: {
92
+ level: severityToLevel[issue.severity] || 'warning'
93
+ },
94
+ properties: issue.metadata || {}
95
+ });
96
+ }
97
+ }
98
+
99
+ // Build results
100
+ const results = issues.map(issue => {
101
+ const result = {
102
+ ruleId: issue.ruleId,
103
+ level: severityToLevel[issue.severity] || 'warning',
104
+ message: { text: issue.message },
105
+ locations: [{
106
+ physicalLocation: {
107
+ artifactLocation: { uri: file_path },
108
+ region: {
109
+ startLine: (issue.line || 0) + 1,
110
+ startColumn: (issue.column || 0) + 1
111
+ }
112
+ }
113
+ }]
114
+ };
115
+
116
+ // Add fix if available
117
+ if (issue.suggested_fix && issue.suggested_fix.fixed) {
118
+ result.fixes = [{
119
+ description: { text: issue.suggested_fix.description || 'Apply security fix' },
120
+ artifactChanges: [{
121
+ artifactLocation: { uri: file_path },
122
+ replacements: [{
123
+ deletedRegion: {
124
+ startLine: (issue.line || 0) + 1,
125
+ startColumn: 1,
126
+ endLine: (issue.line || 0) + 1,
127
+ endColumn: (issue.line_content?.length || 0) + 1
128
+ },
129
+ insertedContent: { text: issue.suggested_fix.fixed }
130
+ }]
131
+ }]
132
+ }];
133
+ }
134
+
135
+ return result;
136
+ });
137
+
138
+ return {
139
+ $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
140
+ version: '2.1.0',
141
+ runs: [{
142
+ tool: {
143
+ driver: {
144
+ name: 'agent-security-scanner-mcp',
145
+ version: '3.1.0',
146
+ informationUri: 'https://github.com/sinewaveai/agent-security-scanner-mcp',
147
+ rules: Array.from(rulesMap.values())
148
+ }
149
+ },
150
+ results: results
151
+ }]
152
+ };
153
+ }