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/README.md +69 -1
- package/index.js +31 -2428
- package/package.json +5 -1
- package/src/analyzer.py +119 -0
- package/src/cli/demo.js +238 -0
- package/src/cli/doctor.js +273 -0
- package/src/cli/init.js +288 -0
- package/src/fix-patterns.js +698 -0
- package/src/tools/check-package.js +169 -0
- package/src/tools/fix-security.js +115 -0
- package/src/tools/scan-packages.js +154 -0
- package/src/tools/scan-prompt.js +570 -0
- package/src/tools/scan-security.js +117 -0
- package/src/utils.js +153 -0
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
|
+
}
|