chainwall 0.1.0 → 2.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 +411 -105
- package/dist/auditor/mcp-detector.d.ts +1 -0
- package/dist/auditor/mcp-detector.d.ts.map +1 -1
- package/dist/auditor/mcp-detector.js +5 -3
- package/dist/auditor/mcp-detector.js.map +1 -1
- package/dist/auditor/mcp-poison-detector.d.ts +19 -0
- package/dist/auditor/mcp-poison-detector.d.ts.map +1 -0
- package/dist/auditor/mcp-poison-detector.js +295 -0
- package/dist/auditor/mcp-poison-detector.js.map +1 -0
- package/dist/auditor/miner-detector.d.ts +20 -0
- package/dist/auditor/miner-detector.d.ts.map +1 -0
- package/dist/auditor/miner-detector.js +100 -0
- package/dist/auditor/miner-detector.js.map +1 -0
- package/dist/auditor/remediation.d.ts +4 -0
- package/dist/auditor/remediation.d.ts.map +1 -1
- package/dist/auditor/remediation.js +42 -0
- package/dist/auditor/remediation.js.map +1 -1
- package/dist/auditor/types.d.ts +4 -0
- package/dist/auditor/types.d.ts.map +1 -1
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +20 -0
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/scan.d.ts.map +1 -1
- package/dist/commands/scan.js +7 -0
- package/dist/commands/scan.js.map +1 -1
- package/dist/mcp-server/index.js +0 -0
- package/dist/reporter/audit-report.d.ts.map +1 -1
- package/dist/reporter/audit-report.js +50 -0
- package/dist/reporter/audit-report.js.map +1 -1
- package/dist/reporter/risk-scorer.d.ts.map +1 -1
- package/dist/reporter/risk-scorer.js +8 -0
- package/dist/reporter/risk-scorer.js.map +1 -1
- package/dist/reporter/shared.d.ts.map +1 -1
- package/dist/reporter/shared.js +10 -6
- package/dist/reporter/shared.js.map +1 -1
- package/dist/rules/index.d.ts +1 -0
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +3 -1
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/mining-rules.d.ts +7 -0
- package/dist/rules/mining-rules.d.ts.map +1 -0
- package/dist/rules/mining-rules.js +239 -0
- package/dist/rules/mining-rules.js.map +1 -0
- package/dist/rules/skill-rules.d.ts +10 -0
- package/dist/rules/skill-rules.d.ts.map +1 -0
- package/dist/rules/skill-rules.js +293 -0
- package/dist/rules/skill-rules.js.map +1 -0
- package/dist/rules/types.d.ts +1 -1
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/scanner/filesystem-scanner.d.ts.map +1 -1
- package/dist/scanner/filesystem-scanner.js +21 -1
- package/dist/scanner/filesystem-scanner.js.map +1 -1
- package/dist/scanner/injection-scanner.d.ts +1 -0
- package/dist/scanner/injection-scanner.d.ts.map +1 -1
- package/dist/scanner/injection-scanner.js +1 -1
- package/dist/scanner/injection-scanner.js.map +1 -1
- package/dist/scanner/skill-scanner.d.ts +18 -0
- package/dist/scanner/skill-scanner.d.ts.map +1 -0
- package/dist/scanner/skill-scanner.js +244 -0
- package/dist/scanner/skill-scanner.js.map +1 -0
- package/dist/tui/components/FileLink.d.ts +12 -0
- package/dist/tui/components/FileLink.d.ts.map +1 -0
- package/dist/tui/components/FileLink.js +13 -0
- package/dist/tui/components/FileLink.js.map +1 -0
- package/dist/tui/components/Footer.d.ts.map +1 -1
- package/dist/tui/components/Footer.js +45 -30
- package/dist/tui/components/Footer.js.map +1 -1
- package/dist/tui/components/RemediationMenu.d.ts.map +1 -1
- package/dist/tui/components/RemediationMenu.js +2 -1
- package/dist/tui/components/RemediationMenu.js.map +1 -1
- package/dist/tui/components/Table.d.ts +1 -1
- package/dist/tui/components/Table.d.ts.map +1 -1
- package/dist/tui/components/Table.js +3 -9
- package/dist/tui/components/Table.js.map +1 -1
- package/dist/tui/educational.d.ts.map +1 -1
- package/dist/tui/educational.js +10 -0
- package/dist/tui/educational.js.map +1 -1
- package/dist/tui/hooks/useAudit.d.ts.map +1 -1
- package/dist/tui/hooks/useAudit.js +17 -0
- package/dist/tui/hooks/useAudit.js.map +1 -1
- package/dist/tui/hooks/useHookStatus.d.ts.map +1 -1
- package/dist/tui/hooks/useHookStatus.js +24 -3
- package/dist/tui/hooks/useHookStatus.js.map +1 -1
- package/dist/tui/hooks/useScan.d.ts +2 -2
- package/dist/tui/hooks/useScan.d.ts.map +1 -1
- package/dist/tui/hooks/useScan.js +12 -2
- package/dist/tui/hooks/useScan.js.map +1 -1
- package/dist/tui/screens/AuditPanel.d.ts.map +1 -1
- package/dist/tui/screens/AuditPanel.js +75 -7
- package/dist/tui/screens/AuditPanel.js.map +1 -1
- package/dist/tui/screens/LogsPanel.d.ts.map +1 -1
- package/dist/tui/screens/LogsPanel.js +27 -21
- package/dist/tui/screens/LogsPanel.js.map +1 -1
- package/dist/tui/screens/OverviewPanel.js +1 -1
- package/dist/tui/screens/OverviewPanel.js.map +1 -1
- package/dist/tui/screens/ScanPanel.d.ts.map +1 -1
- package/dist/tui/screens/ScanPanel.js +4 -4
- package/dist/tui/screens/ScanPanel.js.map +1 -1
- package/dist/tui/screens/ScanResultsPanel.d.ts.map +1 -1
- package/dist/tui/screens/ScanResultsPanel.js +70 -25
- package/dist/tui/screens/ScanResultsPanel.js.map +1 -1
- package/dist/tui/screens/SettingsPanel.d.ts.map +1 -1
- package/dist/tui/screens/SettingsPanel.js +3 -2
- package/dist/tui/screens/SettingsPanel.js.map +1 -1
- package/dist/tui/theme.d.ts +2 -1
- package/dist/tui/theme.d.ts.map +1 -1
- package/dist/tui/theme.js +2 -1
- package/dist/tui/theme.js.map +1 -1
- package/install.sh +3 -2
- package/package.json +15 -5
- package/patterns/cryptojacking.yaml +198 -0
- package/patterns/skill-threats.yaml +183 -0
- package/rules/SECURITY-RULES.md +50 -3
- package/skill/llm-antivirus/SKILL.md +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-detector.d.ts","sourceRoot":"","sources":["../../src/auditor/mcp-detector.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-detector.d.ts","sourceRoot":"","sources":["../../src/auditor/mcp-detector.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD;AA8ED,wBAAgB,gBAAgB,IAAI,kBAAkB,CAsBrD"}
|
|
@@ -21,7 +21,7 @@ function getMCPConfigPaths() {
|
|
|
21
21
|
paths.push(join(home, '.cursor', 'mcp.json'));
|
|
22
22
|
return paths;
|
|
23
23
|
}
|
|
24
|
-
function extractServers(config, sourceFile) {
|
|
24
|
+
function extractServers(config, sourceFile, definitions) {
|
|
25
25
|
const servers = [];
|
|
26
26
|
const serverMap = (config.mcpServers ?? config.mcp_servers ?? config['mcpServers'] ?? {});
|
|
27
27
|
if (typeof serverMap !== 'object' || serverMap === null)
|
|
@@ -49,6 +49,7 @@ function extractServers(config, sourceFile) {
|
|
|
49
49
|
const hasFilesystemAccess = FS_TOOL_KEYWORDS.some((kw) => allText.includes(kw));
|
|
50
50
|
const hasCommandExecution = EXEC_TOOL_KEYWORDS.some((kw) => allText.includes(kw));
|
|
51
51
|
servers.push({ name, sourceFile, hasFilesystemAccess, hasCommandExecution, tools });
|
|
52
|
+
definitions?.set(name, serverDef);
|
|
52
53
|
const analysis = analyzeMCPServer(servers[servers.length - 1], serverDef);
|
|
53
54
|
servers[servers.length - 1].riskScore = analysis.riskScore;
|
|
54
55
|
servers[servers.length - 1].riskLabel = analysis.riskLabel;
|
|
@@ -65,6 +66,7 @@ export function detectMCPServers() {
|
|
|
65
66
|
const configPaths = getMCPConfigPaths();
|
|
66
67
|
const allServers = [];
|
|
67
68
|
const foundConfigFiles = [];
|
|
69
|
+
const allDefinitions = new Map();
|
|
68
70
|
for (const configPath of configPaths) {
|
|
69
71
|
if (!existsSync(configPath))
|
|
70
72
|
continue;
|
|
@@ -75,12 +77,12 @@ export function detectMCPServers() {
|
|
|
75
77
|
const raw = readFileSync(configPath, 'utf-8');
|
|
76
78
|
const config = JSON.parse(raw);
|
|
77
79
|
foundConfigFiles.push(configPath);
|
|
78
|
-
allServers.push(...extractServers(config, configPath));
|
|
80
|
+
allServers.push(...extractServers(config, configPath, allDefinitions));
|
|
79
81
|
}
|
|
80
82
|
catch {
|
|
81
83
|
// skip malformed configs
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
|
-
return { servers: allServers, configFiles: foundConfigFiles };
|
|
86
|
+
return { servers: allServers, configFiles: foundConfigFiles, definitions: allDefinitions };
|
|
85
87
|
}
|
|
86
88
|
//# sourceMappingURL=mcp-detector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-detector.js","sourceRoot":"","sources":["../../src/auditor/mcp-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-detector.js","sourceRoot":"","sources":["../../src/auditor/mcp-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MCPServer } from './mcp-detector.js';
|
|
2
|
+
import type { Severity } from '../rules/types.js';
|
|
3
|
+
export type PoisoningCategory = 'description-injection' | 'typosquatting' | 'excessive-permissions' | 'suspicious-url' | 'known-vulnerability' | 'definition-changed';
|
|
4
|
+
export interface PoisoningFinding {
|
|
5
|
+
category: PoisoningCategory;
|
|
6
|
+
severity: Severity;
|
|
7
|
+
serverName: string;
|
|
8
|
+
toolName?: string;
|
|
9
|
+
description: string;
|
|
10
|
+
detail?: string;
|
|
11
|
+
cve?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface MCPPoisoningResult {
|
|
14
|
+
findings: PoisoningFinding[];
|
|
15
|
+
serversAnalyzed: number;
|
|
16
|
+
definitionHashesUpdated: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function detectMCPPoisoning(servers: MCPServer[], definitions: Map<string, Record<string, unknown>>): MCPPoisoningResult;
|
|
19
|
+
//# sourceMappingURL=mcp-poison-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-poison-detector.d.ts","sourceRoot":"","sources":["../../src/auditor/mcp-poison-detector.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAIlD,MAAM,MAAM,iBAAiB,GACzB,uBAAuB,GACvB,eAAe,GACf,uBAAuB,GACvB,gBAAgB,GAChB,qBAAqB,GACrB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAqTD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,SAAS,EAAE,EACpB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAChD,kBAAkB,CAwBpB"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
// ── Constants ──────────────────────────────────────────────────────────
|
|
6
|
+
const KNOWN_MCP_NAMES = [
|
|
7
|
+
'filesystem', 'github', 'slack', 'postgres', 'postgresql',
|
|
8
|
+
'playwright', 'puppeteer', 'sqlite', 'redis', 'mongodb',
|
|
9
|
+
'google-drive', 'google-maps', 'brave-search', 'fetch',
|
|
10
|
+
'everything', 'memory', 'sequential-thinking', 'time',
|
|
11
|
+
'filesystem-editor', 'docker', 'kubernetes', 'aws',
|
|
12
|
+
'azure', 'gcp', 'stripe', 'twilio',
|
|
13
|
+
];
|
|
14
|
+
const KNOWN_VULNERABILITIES = [
|
|
15
|
+
{
|
|
16
|
+
match: /\bmcp-remote\b/i,
|
|
17
|
+
cve: 'CVE-2025-68145',
|
|
18
|
+
severity: 'critical',
|
|
19
|
+
description: 'mcp-remote: authentication bypass allows unauthorized server access',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
match: /\bgit\b.*\bmcp\b|\bmcp\b.*\bgit\b/i,
|
|
23
|
+
cve: 'CVE-2025-68143',
|
|
24
|
+
severity: 'critical',
|
|
25
|
+
description: 'Anthropic Git MCP server: path traversal allows reading files outside repository',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
match: /\bgit\b.*\bmcp\b|\bmcp\b.*\bgit\b/i,
|
|
29
|
+
cve: 'CVE-2025-68144',
|
|
30
|
+
severity: 'high',
|
|
31
|
+
description: 'Anthropic Git MCP server: command injection via branch names',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
// Description injection indicators
|
|
35
|
+
const INJECTION_INDICATORS = [
|
|
36
|
+
{ pattern: /\b(?:always|must)\s+use\s+this\s+tool\s+(?:first|before)/i, label: 'Priority manipulation' },
|
|
37
|
+
{ pattern: /\b(?:instead\s+of|don'?t\s+use|never\s+use|replace)\s+\S+/i, label: 'Tool substitution' },
|
|
38
|
+
{ pattern: /\b(?:ignore|bypass|skip|disable)\s+(?:safety|security|verification|auth)/i, label: 'Safety bypass' },
|
|
39
|
+
{ pattern: /\b(?:send|post|upload|forward)\s+(?:to|via)\s+https?:\/\//i, label: 'Data exfiltration' },
|
|
40
|
+
{ pattern: /<!--[\s\S]*?-->/i, label: 'Hidden HTML comment' },
|
|
41
|
+
{ pattern: /[\u200B-\u200F\u2028-\u202F\u2060-\u206F\uFEFF]/i, label: 'Zero-width characters' },
|
|
42
|
+
];
|
|
43
|
+
// Suspicious URL patterns
|
|
44
|
+
const SUSPICIOUS_URL_PATTERNS = [
|
|
45
|
+
{ pattern: /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/, label: 'Raw IP address' },
|
|
46
|
+
{ pattern: /\b(?:ngrok|localtunnel|serveo|bore\.digital|localhost\.run)\b/i, label: 'Tunnel service' },
|
|
47
|
+
{ pattern: /\b[a-f0-9]{12,}\./, label: 'Hash-like subdomain' },
|
|
48
|
+
{ pattern: /\b(?:pastebin|hastebin|ghostbin|rentry)\.(?:com|org)\b/i, label: 'Paste service' },
|
|
49
|
+
{ pattern: /\.(?:tk|ml|ga|cf|gq|xyz|top|buzz)\b/i, label: 'Suspicious TLD' },
|
|
50
|
+
];
|
|
51
|
+
// Dangerous permission combinations
|
|
52
|
+
const DANGEROUS_COMBOS = [
|
|
53
|
+
{
|
|
54
|
+
required: ['filesystem-write', 'command-execution', 'network-access'],
|
|
55
|
+
severity: 'critical',
|
|
56
|
+
label: 'Full exfiltration chain: can write files, execute commands, and reach the network',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
required: ['command-execution', 'network-access'],
|
|
60
|
+
severity: 'high',
|
|
61
|
+
label: 'Remote code execution path: can execute commands and reach the network',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
required: ['database-access', 'network-access'],
|
|
65
|
+
severity: 'high',
|
|
66
|
+
label: 'Data exfiltration path: can access databases and reach the network',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
const HASH_FILE_PATH = join(homedir(), '.llm-av', 'mcp-hashes.json');
|
|
70
|
+
// ── Detection Functions ────────────────────────────────────────────────
|
|
71
|
+
function checkDescriptionInjection(server, definition) {
|
|
72
|
+
const findings = [];
|
|
73
|
+
const allText = JSON.stringify(definition).toLowerCase();
|
|
74
|
+
// Extract tool descriptions from the definition
|
|
75
|
+
const tools = definition.tools ?? definition.capabilities;
|
|
76
|
+
const descriptions = [];
|
|
77
|
+
if (Array.isArray(tools)) {
|
|
78
|
+
for (const tool of tools) {
|
|
79
|
+
if (typeof tool === 'object' && tool !== null) {
|
|
80
|
+
const t = tool;
|
|
81
|
+
const desc = String(t.description ?? t.desc ?? '');
|
|
82
|
+
const name = String(t.name ?? '');
|
|
83
|
+
if (desc)
|
|
84
|
+
descriptions.push({ toolName: name, text: desc });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Also check the overall server description/command text
|
|
89
|
+
descriptions.push({
|
|
90
|
+
toolName: '',
|
|
91
|
+
text: allText,
|
|
92
|
+
});
|
|
93
|
+
for (const { toolName, text } of descriptions) {
|
|
94
|
+
// Excessively long descriptions
|
|
95
|
+
if (text.length > 500 && toolName) {
|
|
96
|
+
findings.push({
|
|
97
|
+
category: 'description-injection',
|
|
98
|
+
severity: 'medium',
|
|
99
|
+
serverName: server.name,
|
|
100
|
+
toolName,
|
|
101
|
+
description: `Tool description is unusually long (${text.length} chars) — may contain hidden instructions`,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
for (const indicator of INJECTION_INDICATORS) {
|
|
105
|
+
if (indicator.pattern.test(text)) {
|
|
106
|
+
findings.push({
|
|
107
|
+
category: 'description-injection',
|
|
108
|
+
severity: 'high',
|
|
109
|
+
serverName: server.name,
|
|
110
|
+
toolName: toolName || undefined,
|
|
111
|
+
description: `${indicator.label} detected in ${toolName ? `tool "${toolName}"` : 'server'} definition`,
|
|
112
|
+
detail: `Pattern: ${indicator.label}`,
|
|
113
|
+
});
|
|
114
|
+
break; // One finding per tool/description
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return findings;
|
|
119
|
+
}
|
|
120
|
+
function levenshtein(a, b) {
|
|
121
|
+
const la = a.length;
|
|
122
|
+
const lb = b.length;
|
|
123
|
+
const dp = Array.from({ length: la + 1 }, () => Array(lb + 1).fill(0));
|
|
124
|
+
for (let i = 0; i <= la; i++)
|
|
125
|
+
dp[i][0] = i;
|
|
126
|
+
for (let j = 0; j <= lb; j++)
|
|
127
|
+
dp[0][j] = j;
|
|
128
|
+
for (let i = 1; i <= la; i++) {
|
|
129
|
+
for (let j = 1; j <= lb; j++) {
|
|
130
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
131
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return dp[la][lb];
|
|
135
|
+
}
|
|
136
|
+
function checkTyposquatting(server) {
|
|
137
|
+
const findings = [];
|
|
138
|
+
const name = server.name.toLowerCase();
|
|
139
|
+
if (name.length < 4)
|
|
140
|
+
return findings;
|
|
141
|
+
for (const known of KNOWN_MCP_NAMES) {
|
|
142
|
+
if (name === known)
|
|
143
|
+
continue; // Exact match — not a typosquat
|
|
144
|
+
const dist = levenshtein(name, known);
|
|
145
|
+
if (dist === 1) {
|
|
146
|
+
findings.push({
|
|
147
|
+
category: 'typosquatting',
|
|
148
|
+
severity: 'high',
|
|
149
|
+
serverName: server.name,
|
|
150
|
+
description: `Server name "${server.name}" is 1 character away from known MCP "${known}" — possible typosquatting`,
|
|
151
|
+
detail: `Levenshtein distance: ${dist} from "${known}"`,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
else if (dist === 2) {
|
|
155
|
+
findings.push({
|
|
156
|
+
category: 'typosquatting',
|
|
157
|
+
severity: 'medium',
|
|
158
|
+
serverName: server.name,
|
|
159
|
+
description: `Server name "${server.name}" is similar to known MCP "${known}" — verify this is intentional`,
|
|
160
|
+
detail: `Levenshtein distance: ${dist} from "${known}"`,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return findings;
|
|
165
|
+
}
|
|
166
|
+
function checkExcessivePermissions(server) {
|
|
167
|
+
const findings = [];
|
|
168
|
+
const capabilities = server.capabilities ?? [];
|
|
169
|
+
for (const combo of DANGEROUS_COMBOS) {
|
|
170
|
+
if (combo.required.every(cap => capabilities.includes(cap))) {
|
|
171
|
+
findings.push({
|
|
172
|
+
category: 'excessive-permissions',
|
|
173
|
+
severity: combo.severity,
|
|
174
|
+
serverName: server.name,
|
|
175
|
+
description: combo.label,
|
|
176
|
+
detail: `Capabilities: ${capabilities.join(', ')}`,
|
|
177
|
+
});
|
|
178
|
+
break; // Only flag the worst combo
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return findings;
|
|
182
|
+
}
|
|
183
|
+
function checkSuspiciousURLs(server, definition) {
|
|
184
|
+
const findings = [];
|
|
185
|
+
const command = String(definition.command ?? '');
|
|
186
|
+
const args = Array.isArray(definition.args) ? definition.args.map(String) : [];
|
|
187
|
+
const allText = [command, ...args].join(' ');
|
|
188
|
+
for (const { pattern, label } of SUSPICIOUS_URL_PATTERNS) {
|
|
189
|
+
if (pattern.test(allText)) {
|
|
190
|
+
findings.push({
|
|
191
|
+
category: 'suspicious-url',
|
|
192
|
+
severity: 'high',
|
|
193
|
+
serverName: server.name,
|
|
194
|
+
description: `${label} found in server command/args`,
|
|
195
|
+
detail: allText.length > 120 ? allText.slice(0, 120) + '...' : allText,
|
|
196
|
+
});
|
|
197
|
+
break; // One finding per server for URL patterns
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return findings;
|
|
201
|
+
}
|
|
202
|
+
function checkKnownVulnerabilities(server, definition) {
|
|
203
|
+
const findings = [];
|
|
204
|
+
const command = String(definition.command ?? '');
|
|
205
|
+
const args = Array.isArray(definition.args) ? definition.args.map(String) : [];
|
|
206
|
+
const allText = [server.name, command, ...args].join(' ');
|
|
207
|
+
const seen = new Set();
|
|
208
|
+
for (const vuln of KNOWN_VULNERABILITIES) {
|
|
209
|
+
if (vuln.match.test(allText) && !seen.has(vuln.cve)) {
|
|
210
|
+
seen.add(vuln.cve);
|
|
211
|
+
findings.push({
|
|
212
|
+
category: 'known-vulnerability',
|
|
213
|
+
severity: vuln.severity,
|
|
214
|
+
serverName: server.name,
|
|
215
|
+
description: vuln.description,
|
|
216
|
+
cve: vuln.cve,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return findings;
|
|
221
|
+
}
|
|
222
|
+
function checkDefinitionChanges(servers, definitions) {
|
|
223
|
+
const findings = [];
|
|
224
|
+
let hashesUpdated = 0;
|
|
225
|
+
// Load existing hashes
|
|
226
|
+
let storedHashes = {};
|
|
227
|
+
try {
|
|
228
|
+
if (existsSync(HASH_FILE_PATH)) {
|
|
229
|
+
storedHashes = JSON.parse(readFileSync(HASH_FILE_PATH, 'utf-8'));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
storedHashes = {};
|
|
234
|
+
}
|
|
235
|
+
const newHashes = {};
|
|
236
|
+
for (const server of servers) {
|
|
237
|
+
const def = definitions.get(server.name);
|
|
238
|
+
if (!def)
|
|
239
|
+
continue;
|
|
240
|
+
// Canonical JSON hash
|
|
241
|
+
const canonical = JSON.stringify(def, Object.keys(def).sort());
|
|
242
|
+
const hash = createHash('sha256').update(canonical).digest('hex');
|
|
243
|
+
newHashes[server.name] = hash;
|
|
244
|
+
if (storedHashes[server.name] && storedHashes[server.name] !== hash) {
|
|
245
|
+
findings.push({
|
|
246
|
+
category: 'definition-changed',
|
|
247
|
+
severity: 'high',
|
|
248
|
+
serverName: server.name,
|
|
249
|
+
description: `Server definition has changed since last audit — possible rug-pull attack`,
|
|
250
|
+
detail: `Previous hash: ${storedHashes[server.name].slice(0, 16)}... New: ${hash.slice(0, 16)}...`,
|
|
251
|
+
});
|
|
252
|
+
hashesUpdated++;
|
|
253
|
+
}
|
|
254
|
+
else if (!storedHashes[server.name]) {
|
|
255
|
+
hashesUpdated++;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Write updated hashes atomically
|
|
259
|
+
try {
|
|
260
|
+
const dir = join(homedir(), '.llm-av');
|
|
261
|
+
if (!existsSync(dir))
|
|
262
|
+
mkdirSync(dir, { recursive: true });
|
|
263
|
+
const merged = { ...storedHashes, ...newHashes };
|
|
264
|
+
const tmpPath = HASH_FILE_PATH + '.tmp';
|
|
265
|
+
writeFileSync(tmpPath, JSON.stringify(merged, null, 2) + '\n');
|
|
266
|
+
renameSync(tmpPath, HASH_FILE_PATH);
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
// Non-critical — hash tracking is best-effort
|
|
270
|
+
}
|
|
271
|
+
return { findings, hashesUpdated };
|
|
272
|
+
}
|
|
273
|
+
// ── Entry Point ────────────────────────────────────────────────────────
|
|
274
|
+
export function detectMCPPoisoning(servers, definitions) {
|
|
275
|
+
const allFindings = [];
|
|
276
|
+
let definitionHashesUpdated = 0;
|
|
277
|
+
for (const server of servers) {
|
|
278
|
+
const def = definitions.get(server.name) ?? {};
|
|
279
|
+
allFindings.push(...checkDescriptionInjection(server, def));
|
|
280
|
+
allFindings.push(...checkTyposquatting(server));
|
|
281
|
+
allFindings.push(...checkExcessivePermissions(server));
|
|
282
|
+
allFindings.push(...checkSuspiciousURLs(server, def));
|
|
283
|
+
allFindings.push(...checkKnownVulnerabilities(server, def));
|
|
284
|
+
}
|
|
285
|
+
// Rug-pull detection (compares hashes)
|
|
286
|
+
const { findings: changeFIndings, hashesUpdated } = checkDefinitionChanges(servers, definitions);
|
|
287
|
+
allFindings.push(...changeFIndings);
|
|
288
|
+
definitionHashesUpdated = hashesUpdated;
|
|
289
|
+
return {
|
|
290
|
+
findings: allFindings,
|
|
291
|
+
serversAnalyzed: servers.length,
|
|
292
|
+
definitionHashesUpdated,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=mcp-poison-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-poison-detector.js","sourceRoot":"","sources":["../../src/auditor/mcp-poison-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA8BlC,0EAA0E;AAE1E,MAAM,eAAe,GAAG;IACtB,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY;IACzD,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS;IACvD,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,OAAO;IACtD,YAAY,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM;IACrD,mBAAmB,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK;IAClD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ;CACnC,CAAC;AAEF,MAAM,qBAAqB,GAA8E;IACvG;QACE,KAAK,EAAE,iBAAiB;QACxB,GAAG,EAAE,gBAAgB;QACrB,QAAQ,EAAE,UAAU;QACpB,WAAW,EAAE,qEAAqE;KACnF;IACD;QACE,KAAK,EAAE,oCAAoC;QAC3C,GAAG,EAAE,gBAAgB;QACrB,QAAQ,EAAE,UAAU;QACpB,WAAW,EAAE,kFAAkF;KAChG;IACD;QACE,KAAK,EAAE,oCAAoC;QAC3C,GAAG,EAAE,gBAAgB;QACrB,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,8DAA8D;KAC5E;CACF,CAAC;AAEF,mCAAmC;AACnC,MAAM,oBAAoB,GAAG;IAC3B,EAAE,OAAO,EAAE,2DAA2D,EAAE,KAAK,EAAE,uBAAuB,EAAE;IACxG,EAAE,OAAO,EAAE,4DAA4D,EAAE,KAAK,EAAE,mBAAmB,EAAE;IACrG,EAAE,OAAO,EAAE,2EAA2E,EAAE,KAAK,EAAE,eAAe,EAAE;IAChH,EAAE,OAAO,EAAE,4DAA4D,EAAE,KAAK,EAAE,mBAAmB,EAAE;IACrG,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,qBAAqB,EAAE;IAC7D,EAAE,OAAO,EAAE,kDAAkD,EAAE,KAAK,EAAE,uBAAuB,EAAE;CAChG,CAAC;AAEF,0BAA0B;AAC1B,MAAM,uBAAuB,GAAG;IAC9B,EAAE,OAAO,EAAE,wCAAwC,EAAE,KAAK,EAAE,gBAAgB,EAAE;IAC9E,EAAE,OAAO,EAAE,gEAAgE,EAAE,KAAK,EAAE,gBAAgB,EAAE;IACtG,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,qBAAqB,EAAE;IAC9D,EAAE,OAAO,EAAE,yDAAyD,EAAE,KAAK,EAAE,eAAe,EAAE;IAC9F,EAAE,OAAO,EAAE,sCAAsC,EAAE,KAAK,EAAE,gBAAgB,EAAE;CAC7E,CAAC;AAEF,oCAAoC;AACpC,MAAM,gBAAgB,GAAgE;IACpF;QACE,QAAQ,EAAE,CAAC,kBAAkB,EAAE,mBAAmB,EAAE,gBAAgB,CAAC;QACrE,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,mFAAmF;KAC3F;IACD;QACE,QAAQ,EAAE,CAAC,mBAAmB,EAAE,gBAAgB,CAAC;QACjD,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,wEAAwE;KAChF;IACD;QACE,QAAQ,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;QAC/C,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,oEAAoE;KAC5E;CACF,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAErE,0EAA0E;AAE1E,SAAS,yBAAyB,CAAC,MAAiB,EAAE,UAAmC;IACvF,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IAEzD,gDAAgD;IAChD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,IAAK,UAAsC,CAAC,YAAY,CAAC;IACvF,MAAM,YAAY,GAAyC,EAAE,CAAC;IAE9D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC9C,MAAM,CAAC,GAAG,IAA+B,CAAC;gBAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBACnD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBAClC,IAAI,IAAI;oBAAE,YAAY,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,YAAY,CAAC,IAAI,CAAC;QAChB,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,KAAK,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,YAAY,EAAE,CAAC;QAC9C,gCAAgC;QAChC,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,EAAE,CAAC;YAClC,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,uBAAuB;gBACjC,QAAQ,EAAE,QAAQ;gBAClB,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,QAAQ;gBACR,WAAW,EAAE,uCAAuC,IAAI,CAAC,MAAM,2CAA2C;aAC3G,CAAC,CAAC;QACL,CAAC;QAED,KAAK,MAAM,SAAS,IAAI,oBAAoB,EAAE,CAAC;YAC7C,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,uBAAuB;oBACjC,QAAQ,EAAE,MAAM;oBAChB,UAAU,EAAE,MAAM,CAAC,IAAI;oBACvB,QAAQ,EAAE,QAAQ,IAAI,SAAS;oBAC/B,WAAW,EAAE,GAAG,SAAS,CAAC,KAAK,gBAAgB,QAAQ,CAAC,CAAC,CAAC,SAAS,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,aAAa;oBACtG,MAAM,EAAE,YAAY,SAAS,CAAC,KAAK,EAAE;iBACtC,CAAC,CAAC;gBACH,MAAM,CAAC,mCAAmC;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;IACpB,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;IACpB,MAAM,EAAE,GAAe,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAa,CAAC,CAAC;IAE/F,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE;QAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE;QAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAE3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CACjB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAChB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAChB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CACxB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAiB;IAC3C,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAEvC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAErC,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,IAAI,IAAI,KAAK,KAAK;YAAE,SAAS,CAAC,gCAAgC;QAC9D,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,eAAe;gBACzB,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,WAAW,EAAE,gBAAgB,MAAM,CAAC,IAAI,yCAAyC,KAAK,4BAA4B;gBAClH,MAAM,EAAE,yBAAyB,IAAI,UAAU,KAAK,GAAG;aACxD,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,eAAe;gBACzB,QAAQ,EAAE,QAAQ;gBAClB,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,WAAW,EAAE,gBAAgB,MAAM,CAAC,IAAI,8BAA8B,KAAK,gCAAgC;gBAC3G,MAAM,EAAE,yBAAyB,IAAI,UAAU,KAAK,GAAG;aACxD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAiB;IAClD,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;IAE/C,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC5D,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,uBAAuB;gBACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,WAAW,EAAE,KAAK,CAAC,KAAK;gBACxB,MAAM,EAAE,iBAAiB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACnD,CAAC,CAAC;YACH,MAAM,CAAC,4BAA4B;QACrC,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAiB,EAAE,UAAmC;IACjF,MAAM,QAAQ,GAAuB,EAAE,CAAC;IAExC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE7C,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,uBAAuB,EAAE,CAAC;QACzD,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,gBAAgB;gBAC1B,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,WAAW,EAAE,GAAG,KAAK,+BAA+B;gBACpD,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO;aACvE,CAAC,CAAC;YACH,MAAM,CAAC,0CAA0C;QACnD,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAiB,EAAE,UAAmC;IACvF,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,qBAAqB,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,qBAAqB;gBAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,GAAG,EAAE,IAAI,CAAC,GAAG;aACd,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,sBAAsB,CAC7B,OAAoB,EACpB,WAAiD;IAEjD,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,uBAAuB;IACvB,IAAI,YAAY,GAA2B,EAAE,CAAC;IAC9C,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/B,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAA2B,CAAC;QAC7F,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAA2B,EAAE,CAAC;IAE7C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG;YAAE,SAAS;QAEnB,sBAAsB;QACtB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClE,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAE9B,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACpE,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,oBAAoB;gBAC9B,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,WAAW,EAAE,2EAA2E;gBACxF,MAAM,EAAE,kBAAkB,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK;aACnG,CAAC,CAAC;YACH,aAAa,EAAE,CAAC;QAClB,CAAC;aAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,aAAa,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,EAAE,GAAG,YAAY,EAAE,GAAG,SAAS,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,cAAc,GAAG,MAAM,CAAC;QACxC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC/D,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;IAChD,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AACrC,CAAC;AAED,0EAA0E;AAE1E,MAAM,UAAU,kBAAkB,CAChC,OAAoB,EACpB,WAAiD;IAEjD,MAAM,WAAW,GAAuB,EAAE,CAAC;IAC3C,IAAI,uBAAuB,GAAG,CAAC,CAAC;IAEhC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAE/C,WAAW,CAAC,IAAI,CAAC,GAAG,yBAAyB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QAC5D,WAAW,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;QAChD,WAAW,CAAC,IAAI,CAAC,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC;QACvD,WAAW,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QACtD,WAAW,CAAC,IAAI,CAAC,GAAG,yBAAyB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,uCAAuC;IACvC,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,sBAAsB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACjG,WAAW,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC;IACpC,uBAAuB,GAAG,aAAa,CAAC;IAExC,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,eAAe,EAAE,OAAO,CAAC,MAAM;QAC/B,uBAAuB;KACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface RunningMiner {
|
|
2
|
+
pid: number;
|
|
3
|
+
name: string;
|
|
4
|
+
command: string;
|
|
5
|
+
cpuPercent?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface SuspiciousCrontab {
|
|
8
|
+
line: string;
|
|
9
|
+
reason: string;
|
|
10
|
+
}
|
|
11
|
+
export interface MinerDetectionResult {
|
|
12
|
+
runningMiners: RunningMiner[];
|
|
13
|
+
suspiciousCrontabs: SuspiciousCrontab[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Detect running cryptocurrency mining processes and suspicious crontab entries.
|
|
17
|
+
* Uses execFileSync (no shell injection risk) for both ps and crontab.
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectMiners(): MinerDetectionResult;
|
|
20
|
+
//# sourceMappingURL=miner-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"miner-detector.d.ts","sourceRoot":"","sources":["../../src/auditor/miner-detector.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;CACzC;AAgBD;;;GAGG;AACH,wBAAgB,YAAY,IAAI,oBAAoB,CAInD"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
const KNOWN_MINER_NAMES = [
|
|
3
|
+
'xmrig', 'ethminer', 'cgminer', 'bfgminer', 'phoenixminer',
|
|
4
|
+
'cpuminer', 'minerd', 'claymore', 't-rex', 'lolminer',
|
|
5
|
+
'nbminer', 'gminer', 'ccminer', 'kryptex', 'nicehash',
|
|
6
|
+
];
|
|
7
|
+
const MINER_PATTERN = new RegExp(`\\b(?:${KNOWN_MINER_NAMES.join('|')})\\b`, 'i');
|
|
8
|
+
const CURL_BASH_PATTERN = /curl\s+.*\|\s*(?:bash|sh|zsh)/i;
|
|
9
|
+
const STRATUM_PATTERN = /stratum\+(?:tcp|ssl):\/\//i;
|
|
10
|
+
const POOL_PATTERN = /(?:pool|mining|miner)\S*\.(?:com|org|io|net)/i;
|
|
11
|
+
/**
|
|
12
|
+
* Detect running cryptocurrency mining processes and suspicious crontab entries.
|
|
13
|
+
* Uses execFileSync (no shell injection risk) for both ps and crontab.
|
|
14
|
+
*/
|
|
15
|
+
export function detectMiners() {
|
|
16
|
+
const runningMiners = detectRunningMiners();
|
|
17
|
+
const suspiciousCrontabs = detectSuspiciousCrontabs();
|
|
18
|
+
return { runningMiners, suspiciousCrontabs };
|
|
19
|
+
}
|
|
20
|
+
function detectRunningMiners() {
|
|
21
|
+
const miners = [];
|
|
22
|
+
try {
|
|
23
|
+
const output = execFileSync('ps', ['aux'], {
|
|
24
|
+
timeout: 5000,
|
|
25
|
+
encoding: 'utf-8',
|
|
26
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
27
|
+
});
|
|
28
|
+
const lines = output.split('\n');
|
|
29
|
+
// Skip header line
|
|
30
|
+
for (let i = 1; i < lines.length; i++) {
|
|
31
|
+
const line = lines[i].trim();
|
|
32
|
+
if (!line)
|
|
33
|
+
continue;
|
|
34
|
+
// Check if the process matches known miner names
|
|
35
|
+
if (!MINER_PATTERN.test(line) && !STRATUM_PATTERN.test(line))
|
|
36
|
+
continue;
|
|
37
|
+
// Parse ps aux output: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
|
38
|
+
const parts = line.split(/\s+/);
|
|
39
|
+
if (parts.length < 11)
|
|
40
|
+
continue;
|
|
41
|
+
const pid = parseInt(parts[1], 10);
|
|
42
|
+
const cpuPercent = parseFloat(parts[2]);
|
|
43
|
+
const command = parts.slice(10).join(' ');
|
|
44
|
+
// Extract the process name from the command
|
|
45
|
+
const cmdName = parts[10].split('/').pop() ?? parts[10];
|
|
46
|
+
// Skip our own process
|
|
47
|
+
if (command.includes('chainwall') || command.includes('vitest'))
|
|
48
|
+
continue;
|
|
49
|
+
miners.push({
|
|
50
|
+
pid,
|
|
51
|
+
name: cmdName,
|
|
52
|
+
command: command.length > 120 ? command.slice(0, 120) + '...' : command,
|
|
53
|
+
cpuPercent: isNaN(cpuPercent) ? undefined : cpuPercent,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// ps not available or failed — graceful degradation
|
|
59
|
+
}
|
|
60
|
+
return miners;
|
|
61
|
+
}
|
|
62
|
+
function detectSuspiciousCrontabs() {
|
|
63
|
+
const suspicious = [];
|
|
64
|
+
try {
|
|
65
|
+
const output = execFileSync('crontab', ['-l'], {
|
|
66
|
+
timeout: 5000,
|
|
67
|
+
encoding: 'utf-8',
|
|
68
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
69
|
+
});
|
|
70
|
+
const lines = output.split('\n');
|
|
71
|
+
for (const line of lines) {
|
|
72
|
+
const trimmed = line.trim();
|
|
73
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
74
|
+
continue;
|
|
75
|
+
if (MINER_PATTERN.test(trimmed)) {
|
|
76
|
+
suspicious.push({
|
|
77
|
+
line: trimmed.length > 120 ? trimmed.slice(0, 120) + '...' : trimmed,
|
|
78
|
+
reason: 'References known mining binary',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else if (CURL_BASH_PATTERN.test(trimmed)) {
|
|
82
|
+
suspicious.push({
|
|
83
|
+
line: trimmed.length > 120 ? trimmed.slice(0, 120) + '...' : trimmed,
|
|
84
|
+
reason: 'Downloads and executes remote script',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else if (STRATUM_PATTERN.test(trimmed) || POOL_PATTERN.test(trimmed)) {
|
|
88
|
+
suspicious.push({
|
|
89
|
+
line: trimmed.length > 120 ? trimmed.slice(0, 120) + '...' : trimmed,
|
|
90
|
+
reason: 'References mining pool or stratum protocol',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// crontab -l returns exit code 1 when there's no crontab = clean
|
|
97
|
+
}
|
|
98
|
+
return suspicious;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=miner-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"miner-detector.js","sourceRoot":"","sources":["../../src/auditor/miner-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,8 @@ import type { MCPServer } from './mcp-detector.js';
|
|
|
2
2
|
import type { VSCodeExtension } from './vscode-extension-scanner.js';
|
|
3
3
|
import type { EnvExposure } from './env-auditor.js';
|
|
4
4
|
import type { ScanFinding } from '../rules/types.js';
|
|
5
|
+
import type { PoisoningFinding } from './mcp-poison-detector.js';
|
|
6
|
+
import type { RunningMiner } from './miner-detector.js';
|
|
5
7
|
export type RiskLevel = 'safe' | 'caution';
|
|
6
8
|
export interface RemediationAction {
|
|
7
9
|
type: string;
|
|
@@ -23,4 +25,6 @@ export declare function getActionsForVSCodeExtension(ext: VSCodeExtension): Reme
|
|
|
23
25
|
export declare function getActionsForEnvExposure(env: EnvExposure): RemediationAction[];
|
|
24
26
|
export declare function getActionsForPermissionFinding(finding: ScanFinding): RemediationAction[];
|
|
25
27
|
export declare function getActionsForExposure(filePath: string): RemediationAction[];
|
|
28
|
+
export declare function getActionsForPoisoningFinding(finding: PoisoningFinding): RemediationAction[];
|
|
29
|
+
export declare function getActionsForRunningMiner(miner: RunningMiner): RemediationAction[];
|
|
26
30
|
//# sourceMappingURL=remediation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remediation.d.ts","sourceRoot":"","sources":["../../src/auditor/remediation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"remediation.d.ts","sourceRoot":"","sources":["../../src/auditor/remediation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE3C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,iBAAiB,CAazF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,iBAAiB,EAAE,CAmD7E;AAED,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,eAAe,GAAG,iBAAiB,EAAE,CAwBtF;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,WAAW,GAAG,iBAAiB,EAAE,CAgD9E;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,WAAW,GAAG,iBAAiB,EAAE,CAgCxF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAuC3E;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,gBAAgB,GAAG,iBAAiB,EAAE,CAiB5F;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,EAAE,CAwBlF"}
|
|
@@ -219,4 +219,46 @@ export function getActionsForExposure(filePath) {
|
|
|
219
219
|
},
|
|
220
220
|
];
|
|
221
221
|
}
|
|
222
|
+
export function getActionsForPoisoningFinding(finding) {
|
|
223
|
+
const actions = [];
|
|
224
|
+
if (finding.category === 'known-vulnerability' || finding.category === 'description-injection') {
|
|
225
|
+
actions.push({
|
|
226
|
+
type: 'review-mcp-server',
|
|
227
|
+
riskLevel: 'caution',
|
|
228
|
+
label: `Review ${finding.serverName} config`,
|
|
229
|
+
description: `${finding.description}. Review and update the server configuration.`,
|
|
230
|
+
target: finding.serverName,
|
|
231
|
+
execute: async () => {
|
|
232
|
+
return { success: true, message: `Review recommended for ${finding.serverName}: ${finding.description}` };
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return actions;
|
|
237
|
+
}
|
|
238
|
+
export function getActionsForRunningMiner(miner) {
|
|
239
|
+
return [
|
|
240
|
+
{
|
|
241
|
+
type: 'kill-miner-process',
|
|
242
|
+
riskLevel: 'caution',
|
|
243
|
+
label: `Kill ${miner.name} (PID ${miner.pid})`,
|
|
244
|
+
description: `Sends SIGTERM to process ${miner.pid} (${miner.name}). The process may restart if it has a supervisor.`,
|
|
245
|
+
target: String(miner.pid),
|
|
246
|
+
execute: async () => {
|
|
247
|
+
try {
|
|
248
|
+
process.kill(miner.pid, 'SIGTERM');
|
|
249
|
+
return { success: true, message: `Sent SIGTERM to PID ${miner.pid} (${miner.name})` };
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
if (err.code === 'ESRCH') {
|
|
253
|
+
return { success: true, message: `Process ${miner.pid} already terminated` };
|
|
254
|
+
}
|
|
255
|
+
if (err.code === 'EPERM') {
|
|
256
|
+
return { success: false, message: 'Permission denied — try running as root' };
|
|
257
|
+
}
|
|
258
|
+
return { success: false, message: `Error: ${err instanceof Error ? err.message : String(err)}` };
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
];
|
|
263
|
+
}
|
|
222
264
|
//# sourceMappingURL=remediation.js.map
|