@sulthonzh/mcp-audit 1.1.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 +134 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +165 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/config-loader.d.ts +17 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +72 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/reporter/report-generator.d.ts +7 -0
- package/dist/reporter/report-generator.d.ts.map +1 -0
- package/dist/reporter/report-generator.js +240 -0
- package/dist/reporter/report-generator.js.map +1 -0
- package/dist/reporters/sarif-reporter.d.ts +18 -0
- package/dist/reporters/sarif-reporter.d.ts.map +1 -0
- package/dist/reporters/sarif-reporter.js +148 -0
- package/dist/reporters/sarif-reporter.js.map +1 -0
- package/dist/scanners/config-scanner.d.ts +11 -0
- package/dist/scanners/config-scanner.d.ts.map +1 -0
- package/dist/scanners/config-scanner.js +399 -0
- package/dist/scanners/config-scanner.js.map +1 -0
- package/dist/scanners/docker-scanner.d.ts +13 -0
- package/dist/scanners/docker-scanner.d.ts.map +1 -0
- package/dist/scanners/docker-scanner.js +384 -0
- package/dist/scanners/docker-scanner.js.map +1 -0
- package/dist/scanners/helm-scanner.d.ts +16 -0
- package/dist/scanners/helm-scanner.d.ts.map +1 -0
- package/dist/scanners/helm-scanner.js +385 -0
- package/dist/scanners/helm-scanner.js.map +1 -0
- package/dist/scanners/k8s-scanner.d.ts +14 -0
- package/dist/scanners/k8s-scanner.d.ts.map +1 -0
- package/dist/scanners/k8s-scanner.js +315 -0
- package/dist/scanners/k8s-scanner.js.map +1 -0
- package/dist/scanners/server-scanner.d.ts +13 -0
- package/dist/scanners/server-scanner.d.ts.map +1 -0
- package/dist/scanners/server-scanner.js +346 -0
- package/dist/scanners/server-scanner.js.map +1 -0
- package/dist/types/security-result.d.ts +35 -0
- package/dist/types/security-result.d.ts.map +1 -0
- package/dist/types/security-result.js +3 -0
- package/dist/types/security-result.js.map +1 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +71 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.checkServer = checkServer;
|
|
7
|
+
const rest_1 = require("@octokit/rest");
|
|
8
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
9
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const logger_1 = require("../utils/logger");
|
|
12
|
+
async function checkServer(repository, options, verbose = false) {
|
|
13
|
+
logger_1.logger.info(`Analyzing MCP server: ${repository}`);
|
|
14
|
+
const repoInfo = await parseRepositoryUrl(repository);
|
|
15
|
+
if (!repoInfo) {
|
|
16
|
+
throw new Error(`Invalid repository URL: ${repository}`);
|
|
17
|
+
}
|
|
18
|
+
const result = {
|
|
19
|
+
scanType: 'server',
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
target: repository,
|
|
22
|
+
issues: [],
|
|
23
|
+
score: 0,
|
|
24
|
+
summary: {
|
|
25
|
+
configFilesFound: 0,
|
|
26
|
+
highRiskIssues: 0,
|
|
27
|
+
mediumRiskIssues: 0,
|
|
28
|
+
lowRiskIssues: 0
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
try {
|
|
32
|
+
// Clone repository
|
|
33
|
+
const clonePath = await cloneRepository(repoInfo);
|
|
34
|
+
// Analyze repository
|
|
35
|
+
const analysis = await analyzeRepository(clonePath, options);
|
|
36
|
+
// Calculate trust score
|
|
37
|
+
result.score = calculateTrustScore(analysis, options.trustWeight);
|
|
38
|
+
// Analyze code for vulnerabilities
|
|
39
|
+
const vulnerabilities = await analyzeCodeForVulnerabilities(clonePath, options.scanDepth);
|
|
40
|
+
result.issues.push(...vulnerabilities);
|
|
41
|
+
// Update summary
|
|
42
|
+
result.summary.highRiskIssues = result.issues.filter(i => i.type === 'high').length;
|
|
43
|
+
result.summary.mediumRiskIssues = result.issues.filter(i => i.type === 'medium').length;
|
|
44
|
+
result.summary.lowRiskIssues = result.issues.filter(i => i.type === 'low').length;
|
|
45
|
+
// Cleanup
|
|
46
|
+
await fs_extra_1.default.remove(clonePath);
|
|
47
|
+
if (verbose) {
|
|
48
|
+
logger_1.logger.debug('Repository analysis completed:', analysis);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
logger_1.logger.error(`Error analyzing repository ${repository}:`, error);
|
|
53
|
+
result.issues.push({
|
|
54
|
+
type: 'high',
|
|
55
|
+
category: 'config',
|
|
56
|
+
title: 'Repository Analysis Failed',
|
|
57
|
+
description: `Could not analyze repository: ${repository}`,
|
|
58
|
+
recommendation: 'Check repository accessibility and ensure it contains valid MCP server code',
|
|
59
|
+
evidence: error instanceof Error ? error.message : String(error)
|
|
60
|
+
});
|
|
61
|
+
result.score = 0;
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
async function parseRepositoryUrl(url) {
|
|
66
|
+
let owner, repo;
|
|
67
|
+
if (url.startsWith('https://github.com/')) {
|
|
68
|
+
const parts = url.replace('https://github.com/', '').split('/');
|
|
69
|
+
if (parts.length >= 2) {
|
|
70
|
+
owner = parts[0];
|
|
71
|
+
repo = parts[1].replace('.git', '');
|
|
72
|
+
return {
|
|
73
|
+
url,
|
|
74
|
+
owner,
|
|
75
|
+
repo,
|
|
76
|
+
clonePath: path_1.default.join(process.cwd(), 'temp-clones', `${owner}-${repo}`),
|
|
77
|
+
stars: 0,
|
|
78
|
+
hasTests: false,
|
|
79
|
+
hasCI: false,
|
|
80
|
+
ageInDays: 0
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else if (url.startsWith('github.com/')) {
|
|
85
|
+
const parts = url.replace('github.com/', '').split('/');
|
|
86
|
+
if (parts.length >= 2) {
|
|
87
|
+
owner = parts[0];
|
|
88
|
+
repo = parts[1].replace('.git', '');
|
|
89
|
+
return {
|
|
90
|
+
url: `https://github.com/${owner}/${repo}`,
|
|
91
|
+
owner,
|
|
92
|
+
repo,
|
|
93
|
+
clonePath: path_1.default.join(process.cwd(), 'temp-clones', `${owner}-${repo}`),
|
|
94
|
+
stars: 0,
|
|
95
|
+
hasTests: false,
|
|
96
|
+
hasCI: false,
|
|
97
|
+
ageInDays: 0
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (path_1.default.isAbsolute(url)) {
|
|
102
|
+
// Local path
|
|
103
|
+
const stats = await fs_extra_1.default.stat(url);
|
|
104
|
+
if (stats.isDirectory()) {
|
|
105
|
+
return {
|
|
106
|
+
url: `local:${url}`,
|
|
107
|
+
owner: 'local',
|
|
108
|
+
repo: path_1.default.basename(url),
|
|
109
|
+
clonePath: url,
|
|
110
|
+
stars: 0,
|
|
111
|
+
hasTests: false,
|
|
112
|
+
hasCI: false,
|
|
113
|
+
ageInDays: 0
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
async function cloneRepository(repoInfo) {
|
|
120
|
+
if (repoInfo.url.startsWith('local:')) {
|
|
121
|
+
return repoInfo.clonePath;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(repoInfo.clonePath));
|
|
125
|
+
// Get repository info from GitHub API
|
|
126
|
+
const octokit = new rest_1.Octokit();
|
|
127
|
+
const { data } = await octokit.rest.repos.get({
|
|
128
|
+
owner: repoInfo.owner,
|
|
129
|
+
repo: repoInfo.repo
|
|
130
|
+
});
|
|
131
|
+
repoInfo.stars = data.stargazers_count || 0;
|
|
132
|
+
repoInfo.hasTests = data.topics?.includes('tests') || false;
|
|
133
|
+
repoInfo.hasCI = data.has_issues || false;
|
|
134
|
+
repoInfo.ageInDays = Math.floor((Date.now() - new Date(data.created_at).getTime()) / (1000 * 60 * 60 * 24));
|
|
135
|
+
repoInfo.description = data.description || undefined;
|
|
136
|
+
// Clone the repository
|
|
137
|
+
const git = (0, simple_git_1.default)();
|
|
138
|
+
await git.clone(repoInfo.url, repoInfo.clonePath);
|
|
139
|
+
return repoInfo.clonePath;
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async function analyzeRepository(clonePath, options) {
|
|
146
|
+
const analysis = {
|
|
147
|
+
hasPackageJson: false,
|
|
148
|
+
hasMCPConfig: false,
|
|
149
|
+
hasTests: false,
|
|
150
|
+
hasCI: false,
|
|
151
|
+
language: 'unknown',
|
|
152
|
+
dependencies: 0,
|
|
153
|
+
files: 0,
|
|
154
|
+
size: 0
|
|
155
|
+
};
|
|
156
|
+
try {
|
|
157
|
+
// Check for package.json
|
|
158
|
+
analysis.hasPackageJson = await fs_extra_1.default.pathExists(path_1.default.join(clonePath, 'package.json'));
|
|
159
|
+
// Check for MCP config files
|
|
160
|
+
const mcpFiles = ['mcp.json', 'claude_desktop_config.json', 'config.json'];
|
|
161
|
+
for (const file of mcpFiles) {
|
|
162
|
+
if (await fs_extra_1.default.pathExists(path_1.default.join(clonePath, file))) {
|
|
163
|
+
analysis.hasMCPConfig = true;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Check for tests
|
|
168
|
+
const testDirs = ['test', 'tests', '__tests__', 'spec', 'specs'];
|
|
169
|
+
for (const dir of testDirs) {
|
|
170
|
+
if (await fs_extra_1.default.pathExists(path_1.default.join(clonePath, dir))) {
|
|
171
|
+
analysis.hasTests = true;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// Check for CI files
|
|
176
|
+
const ciFiles = ['.github/workflows', '.gitlab-ci.yml', 'circle.yml', 'travis.yml'];
|
|
177
|
+
for (const file of ciFiles) {
|
|
178
|
+
const filePath = path_1.default.join(clonePath, file);
|
|
179
|
+
if (file.includes('workflows') && await fs_extra_1.default.pathExists(filePath)) {
|
|
180
|
+
const files = await fs_extra_1.default.readdir(filePath);
|
|
181
|
+
analysis.hasCI = files.length > 0;
|
|
182
|
+
}
|
|
183
|
+
else if (await fs_extra_1.default.pathExists(filePath)) {
|
|
184
|
+
analysis.hasCI = true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Get repository stats
|
|
188
|
+
const files = await getAllFiles(clonePath);
|
|
189
|
+
analysis.files = files.length;
|
|
190
|
+
analysis.size = await getDirectorySize(clonePath);
|
|
191
|
+
// Detect language based on files
|
|
192
|
+
analysis.language = detectLanguage(files);
|
|
193
|
+
// Get dependencies count
|
|
194
|
+
if (analysis.hasPackageJson) {
|
|
195
|
+
const packageJson = await fs_extra_1.default.readJson(path_1.default.join(clonePath, 'package.json'));
|
|
196
|
+
analysis.dependencies = Object.keys(packageJson.dependencies || {}).length +
|
|
197
|
+
Object.keys(packageJson.devDependencies || {}).length;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
logger_1.logger.warn('Error during repository analysis:', error);
|
|
202
|
+
}
|
|
203
|
+
return analysis;
|
|
204
|
+
}
|
|
205
|
+
async function analyzeCodeForVulnerabilities(clonePath, depth) {
|
|
206
|
+
const vulnerabilities = [];
|
|
207
|
+
const files = await getAllFiles(clonePath);
|
|
208
|
+
for (const file of files) {
|
|
209
|
+
if (depth > 0 && file.split('/').length > depth) {
|
|
210
|
+
continue; // Skip files beyond scan depth
|
|
211
|
+
}
|
|
212
|
+
const content = await fs_extra_1.default.readFile(file, 'utf8');
|
|
213
|
+
const relativePath = path_1.default.relative(clonePath, file);
|
|
214
|
+
// Check for hardcoded secrets
|
|
215
|
+
const secrets = checkForSecrets(content);
|
|
216
|
+
secrets.forEach(secret => {
|
|
217
|
+
vulnerabilities.push({
|
|
218
|
+
type: 'high',
|
|
219
|
+
category: 'config',
|
|
220
|
+
title: 'Hardcoded Secret Detected',
|
|
221
|
+
description: `Hardcoded secret found in ${relativePath}`,
|
|
222
|
+
recommendation: 'Use environment variables or secure secrets management',
|
|
223
|
+
evidence: `Secret type: ${secret.type}, Line: ${secret.line}`
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
// Check for dangerous functions
|
|
227
|
+
const dangerousFunctions = checkForDangerousFunctions(content);
|
|
228
|
+
dangerousFunctions.forEach(func => {
|
|
229
|
+
vulnerabilities.push({
|
|
230
|
+
type: 'medium',
|
|
231
|
+
category: 'permissions',
|
|
232
|
+
title: 'Dangerous Function Usage',
|
|
233
|
+
description: `Use of potentially dangerous function: ${func}`,
|
|
234
|
+
recommendation: 'Review usage context and ensure proper input validation',
|
|
235
|
+
evidence: `Function: ${func}, File: ${relativePath}`
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
// Check for eval usage
|
|
239
|
+
if (content.includes('eval(')) {
|
|
240
|
+
vulnerabilities.push({
|
|
241
|
+
type: 'high',
|
|
242
|
+
category: 'permissions',
|
|
243
|
+
title: 'eval() Usage',
|
|
244
|
+
description: 'Use of eval() function detected',
|
|
245
|
+
recommendation: 'Avoid eval() for security reasons',
|
|
246
|
+
evidence: `File: ${relativePath}`
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return vulnerabilities;
|
|
251
|
+
}
|
|
252
|
+
function checkForSecrets(content) {
|
|
253
|
+
const vulnerabilities = [];
|
|
254
|
+
const lines = content.split('\n');
|
|
255
|
+
const secretPatterns = [
|
|
256
|
+
/(?:password|passwd|pwd|secret|token|key|api[_-]?key|access[_-]?token)\s*[:=]\s*['"`](.+?)['"`]/gi,
|
|
257
|
+
/bearer\s+(.+?)\s*$/gi,
|
|
258
|
+
/secret['"`]\s*[:=]\s*['"`](.+?)['"`]/gi
|
|
259
|
+
];
|
|
260
|
+
lines.forEach((line, index) => {
|
|
261
|
+
secretPatterns.forEach(pattern => {
|
|
262
|
+
const match = line.match(pattern);
|
|
263
|
+
if (match) {
|
|
264
|
+
vulnerabilities.push({
|
|
265
|
+
type: match[1] ? 'api_key' : 'password',
|
|
266
|
+
line: index + 1
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
return vulnerabilities;
|
|
272
|
+
}
|
|
273
|
+
function checkForDangerousFunctions(content) {
|
|
274
|
+
const dangerousFunctions = [
|
|
275
|
+
'exec', 'spawn', 'child_process', 'fork', 'require',
|
|
276
|
+
'eval', 'Function', 'setTimeout', 'setInterval'
|
|
277
|
+
];
|
|
278
|
+
const found = [];
|
|
279
|
+
const lines = content.split('\n');
|
|
280
|
+
lines.forEach(line => {
|
|
281
|
+
dangerousFunctions.forEach(func => {
|
|
282
|
+
if (line.includes(func + '(')) {
|
|
283
|
+
found.push(func);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
return [...new Set(found)];
|
|
288
|
+
}
|
|
289
|
+
async function getAllFiles(dir) {
|
|
290
|
+
const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
|
|
291
|
+
const files = [];
|
|
292
|
+
for (const entry of entries) {
|
|
293
|
+
const fullPath = path_1.default.join(dir, entry.name);
|
|
294
|
+
if (entry.isDirectory()) {
|
|
295
|
+
files.push(...await getAllFiles(fullPath));
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
files.push(fullPath);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return files;
|
|
302
|
+
}
|
|
303
|
+
async function getDirectorySize(dir) {
|
|
304
|
+
const files = await getAllFiles(dir);
|
|
305
|
+
let size = 0;
|
|
306
|
+
for (const file of files) {
|
|
307
|
+
const stats = await fs_extra_1.default.stat(file);
|
|
308
|
+
size += stats.size;
|
|
309
|
+
}
|
|
310
|
+
return size;
|
|
311
|
+
}
|
|
312
|
+
function detectLanguage(files) {
|
|
313
|
+
const extensions = files.map(f => path_1.default.extname(f)).filter(ext => ext);
|
|
314
|
+
const languageCount = {};
|
|
315
|
+
extensions.forEach(ext => {
|
|
316
|
+
languageCount[ext] = (languageCount[ext] || 0) + 1;
|
|
317
|
+
});
|
|
318
|
+
const mostCommon = Object.entries(languageCount).sort(([, a], [, b]) => b - a)[0];
|
|
319
|
+
return mostCommon ? mostCommon[0] : 'unknown';
|
|
320
|
+
}
|
|
321
|
+
function calculateTrustScore(analysis, weights) {
|
|
322
|
+
let score = 0;
|
|
323
|
+
// Stars weight (normalized, max 1000 stars = full points)
|
|
324
|
+
score += Math.min(analysis.stars / 1000 * weights.stars, weights.stars);
|
|
325
|
+
// Tests weight
|
|
326
|
+
if (analysis.hasTests) {
|
|
327
|
+
score += weights.tests;
|
|
328
|
+
}
|
|
329
|
+
// CI weight
|
|
330
|
+
if (analysis.hasCI) {
|
|
331
|
+
score += weights.ci;
|
|
332
|
+
}
|
|
333
|
+
// Age weight (older repositories get more weight)
|
|
334
|
+
const ageScore = Math.min(analysis.ageInDays / 365 * weights.age, weights.age);
|
|
335
|
+
score += ageScore;
|
|
336
|
+
// Add bonus for proper structure
|
|
337
|
+
if (analysis.hasPackageJson && analysis.hasMCPConfig) {
|
|
338
|
+
score += 0.1;
|
|
339
|
+
}
|
|
340
|
+
// Bonus for language-specific patterns
|
|
341
|
+
if (analysis.language === '.ts' || analysis.language === '.js') {
|
|
342
|
+
score += 0.05;
|
|
343
|
+
}
|
|
344
|
+
return Math.round(score);
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=server-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-scanner.js","sourceRoot":"","sources":["../../src/scanners/server-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface SecurityIssue {
|
|
2
|
+
type: 'high' | 'medium' | 'low';
|
|
3
|
+
category: 'permissions' | 'config' | 'filesystem' | 'network' | 'injection' | 'supply-chain' | 'transport';
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
recommendation: string;
|
|
7
|
+
evidence?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ScanSummary {
|
|
10
|
+
configFilesFound: number;
|
|
11
|
+
highRiskIssues: number;
|
|
12
|
+
mediumRiskIssues: number;
|
|
13
|
+
lowRiskIssues: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SecurityResult {
|
|
16
|
+
scanType: 'config' | 'server';
|
|
17
|
+
timestamp: string;
|
|
18
|
+
target: string;
|
|
19
|
+
issues: SecurityIssue[];
|
|
20
|
+
score: number;
|
|
21
|
+
summary: ScanSummary;
|
|
22
|
+
metadata?: Record<string, any>;
|
|
23
|
+
}
|
|
24
|
+
export interface VulnerabilityDatabaseEntry {
|
|
25
|
+
id: string;
|
|
26
|
+
title: string;
|
|
27
|
+
description: string;
|
|
28
|
+
severity: 'high' | 'medium' | 'low';
|
|
29
|
+
affectedPackages: string[];
|
|
30
|
+
patchedVersions: string[];
|
|
31
|
+
published: string;
|
|
32
|
+
updated: string;
|
|
33
|
+
references?: string[];
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=security-result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-result.d.ts","sourceRoot":"","sources":["../../src/types/security-result.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAChC,QAAQ,EAAE,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,WAAW,CAAC;IAC3G,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-result.js","sourceRoot":"","sources":["../../src/types/security-result.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type LogLevel = 'info' | 'warn' | 'error' | 'debug';
|
|
2
|
+
export interface LoggerOptions {
|
|
3
|
+
verbose?: boolean;
|
|
4
|
+
silent?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare class Logger {
|
|
7
|
+
private options;
|
|
8
|
+
constructor(options?: LoggerOptions);
|
|
9
|
+
private log;
|
|
10
|
+
info(message: string, data?: any): void;
|
|
11
|
+
warn(message: string, data?: any): void;
|
|
12
|
+
error(message: string, data?: any): void;
|
|
13
|
+
debug(message: string, data?: any): void;
|
|
14
|
+
success(message: string): void;
|
|
15
|
+
start(message: string): void;
|
|
16
|
+
separator(): void;
|
|
17
|
+
}
|
|
18
|
+
export declare const logger: Logger;
|
|
19
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAgB;gBAEnB,OAAO,GAAE,aAAkB;IAIvC,OAAO,CAAC,GAAG;IAwCX,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAIvC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAIvC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAIxC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAIxC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI9B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B,SAAS,IAAI,IAAI;CAGlB;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logger = exports.Logger = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
class Logger {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
}
|
|
12
|
+
log(level, message, data) {
|
|
13
|
+
if (this.options.silent)
|
|
14
|
+
return;
|
|
15
|
+
const timestamp = new Date().toISOString();
|
|
16
|
+
const prefix = `[${timestamp}]`;
|
|
17
|
+
const levelIcon = {
|
|
18
|
+
info: 'ℹ️',
|
|
19
|
+
warn: '⚠️',
|
|
20
|
+
error: '❌',
|
|
21
|
+
debug: '🔍'
|
|
22
|
+
}[level];
|
|
23
|
+
let formattedMessage = `${chalk_1.default.gray(prefix)} ${levelIcon} ${message}`;
|
|
24
|
+
if (this.options.verbose) {
|
|
25
|
+
formattedMessage = `${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(levelIcon)} ${message}`;
|
|
26
|
+
}
|
|
27
|
+
switch (level) {
|
|
28
|
+
case 'info':
|
|
29
|
+
console.log(formattedMessage);
|
|
30
|
+
break;
|
|
31
|
+
case 'warn':
|
|
32
|
+
console.warn(chalk_1.default.yellow(formattedMessage));
|
|
33
|
+
break;
|
|
34
|
+
case 'error':
|
|
35
|
+
console.error(chalk_1.default.red(formattedMessage));
|
|
36
|
+
break;
|
|
37
|
+
case 'debug':
|
|
38
|
+
if (this.options.verbose) {
|
|
39
|
+
console.debug(chalk_1.default.gray(formattedMessage));
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
if (data && this.options.verbose) {
|
|
44
|
+
console.log(chalk_1.default.gray(JSON.stringify(data, null, 2)));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
info(message, data) {
|
|
48
|
+
this.log('info', message, data);
|
|
49
|
+
}
|
|
50
|
+
warn(message, data) {
|
|
51
|
+
this.log('warn', message, data);
|
|
52
|
+
}
|
|
53
|
+
error(message, data) {
|
|
54
|
+
this.log('error', message, data);
|
|
55
|
+
}
|
|
56
|
+
debug(message, data) {
|
|
57
|
+
this.log('debug', message, data);
|
|
58
|
+
}
|
|
59
|
+
success(message) {
|
|
60
|
+
console.log(chalk_1.default.green(`✅ ${message}`));
|
|
61
|
+
}
|
|
62
|
+
start(message) {
|
|
63
|
+
console.log(chalk_1.default.blue(`🚀 ${message}`));
|
|
64
|
+
}
|
|
65
|
+
separator() {
|
|
66
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.Logger = Logger;
|
|
70
|
+
exports.logger = new Logger();
|
|
71
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sulthonzh/mcp-audit",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Security scanner for MCP (Model Context Protocol) servers",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mcp-audit": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "ts-node src/cli.ts",
|
|
12
|
+
"start": "node dist/cli.js",
|
|
13
|
+
"test": "node --import tsx --test test/*.test.ts",
|
|
14
|
+
"test:jest": "jest",
|
|
15
|
+
"test:watch": "jest --watch",
|
|
16
|
+
"lint": "eslint src/**/*.ts",
|
|
17
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
18
|
+
"prepare": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"mcp",
|
|
22
|
+
"security",
|
|
23
|
+
"audit",
|
|
24
|
+
"ai",
|
|
25
|
+
"agent",
|
|
26
|
+
"scanner",
|
|
27
|
+
"vulnerability",
|
|
28
|
+
"cli"
|
|
29
|
+
],
|
|
30
|
+
"author": "Sulthonzh",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@octokit/rest": "^19.0.0",
|
|
34
|
+
"axios": "^1.6.0",
|
|
35
|
+
"chalk": "^4.1.2",
|
|
36
|
+
"commander": "^11.0.0",
|
|
37
|
+
"crypto-js": "^4.2.0",
|
|
38
|
+
"fs-extra": "^11.1.0",
|
|
39
|
+
"glob": "^10.3.0",
|
|
40
|
+
"inquirer": "^9.2.0",
|
|
41
|
+
"js-yaml": "^4.1.0",
|
|
42
|
+
"ora": "^7.0.1",
|
|
43
|
+
"simple-git": "^3.20.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/crypto-js": "^4.2.1",
|
|
47
|
+
"@types/fs-extra": "^11.0.4",
|
|
48
|
+
"@types/inquirer": "^9.0.3",
|
|
49
|
+
"@types/jest": "^29.5.0",
|
|
50
|
+
"@types/js-yaml": "^4.0.6",
|
|
51
|
+
"@types/node": "^20.0.0",
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
53
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
54
|
+
"eslint": "^8.0.0",
|
|
55
|
+
"jest": "^29.7.0",
|
|
56
|
+
"ts-jest": "^29.1.0",
|
|
57
|
+
"ts-node": "^10.9.0",
|
|
58
|
+
"tsx": "^4.22.4",
|
|
59
|
+
"typescript": "^5.2.0"
|
|
60
|
+
},
|
|
61
|
+
"files": [
|
|
62
|
+
"dist/**/*",
|
|
63
|
+
"README.md",
|
|
64
|
+
"LICENSE"
|
|
65
|
+
],
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=18.0.0"
|
|
68
|
+
},
|
|
69
|
+
"repository": {
|
|
70
|
+
"type": "git",
|
|
71
|
+
"url": "git+https://github.com/sulthonzh/mcp-audit.git"
|
|
72
|
+
},
|
|
73
|
+
"bugs": {
|
|
74
|
+
"url": "https://github.com/sulthonzh/mcp-audit/issues"
|
|
75
|
+
},
|
|
76
|
+
"homepage": "https://github.com/sulthonzh/mcp-audit#readme"
|
|
77
|
+
}
|