defense-mcp-server 0.6.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.
Files changed (186) hide show
  1. package/CHANGELOG.md +471 -0
  2. package/LICENSE +21 -0
  3. package/README.md +242 -0
  4. package/build/core/auto-installer.d.ts +102 -0
  5. package/build/core/auto-installer.d.ts.map +1 -0
  6. package/build/core/auto-installer.js +833 -0
  7. package/build/core/backup-manager.d.ts +63 -0
  8. package/build/core/backup-manager.d.ts.map +1 -0
  9. package/build/core/backup-manager.js +189 -0
  10. package/build/core/changelog.d.ts +75 -0
  11. package/build/core/changelog.d.ts.map +1 -0
  12. package/build/core/changelog.js +123 -0
  13. package/build/core/command-allowlist.d.ts +129 -0
  14. package/build/core/command-allowlist.d.ts.map +1 -0
  15. package/build/core/command-allowlist.js +849 -0
  16. package/build/core/config.d.ts +79 -0
  17. package/build/core/config.d.ts.map +1 -0
  18. package/build/core/config.js +193 -0
  19. package/build/core/dependency-validator.d.ts +106 -0
  20. package/build/core/dependency-validator.d.ts.map +1 -0
  21. package/build/core/dependency-validator.js +405 -0
  22. package/build/core/distro-adapter.d.ts +177 -0
  23. package/build/core/distro-adapter.d.ts.map +1 -0
  24. package/build/core/distro-adapter.js +481 -0
  25. package/build/core/distro.d.ts +68 -0
  26. package/build/core/distro.d.ts.map +1 -0
  27. package/build/core/distro.js +457 -0
  28. package/build/core/encrypted-state.d.ts +76 -0
  29. package/build/core/encrypted-state.d.ts.map +1 -0
  30. package/build/core/encrypted-state.js +209 -0
  31. package/build/core/executor.d.ts +56 -0
  32. package/build/core/executor.d.ts.map +1 -0
  33. package/build/core/executor.js +350 -0
  34. package/build/core/installer.d.ts +92 -0
  35. package/build/core/installer.d.ts.map +1 -0
  36. package/build/core/installer.js +1072 -0
  37. package/build/core/logger.d.ts +102 -0
  38. package/build/core/logger.d.ts.map +1 -0
  39. package/build/core/logger.js +132 -0
  40. package/build/core/parsers.d.ts +151 -0
  41. package/build/core/parsers.d.ts.map +1 -0
  42. package/build/core/parsers.js +479 -0
  43. package/build/core/policy-engine.d.ts +170 -0
  44. package/build/core/policy-engine.d.ts.map +1 -0
  45. package/build/core/policy-engine.js +656 -0
  46. package/build/core/preflight.d.ts +157 -0
  47. package/build/core/preflight.d.ts.map +1 -0
  48. package/build/core/preflight.js +638 -0
  49. package/build/core/privilege-manager.d.ts +108 -0
  50. package/build/core/privilege-manager.d.ts.map +1 -0
  51. package/build/core/privilege-manager.js +363 -0
  52. package/build/core/rate-limiter.d.ts +67 -0
  53. package/build/core/rate-limiter.d.ts.map +1 -0
  54. package/build/core/rate-limiter.js +129 -0
  55. package/build/core/rollback.d.ts +73 -0
  56. package/build/core/rollback.d.ts.map +1 -0
  57. package/build/core/rollback.js +278 -0
  58. package/build/core/safeguards.d.ts +58 -0
  59. package/build/core/safeguards.d.ts.map +1 -0
  60. package/build/core/safeguards.js +448 -0
  61. package/build/core/sanitizer.d.ts +118 -0
  62. package/build/core/sanitizer.d.ts.map +1 -0
  63. package/build/core/sanitizer.js +459 -0
  64. package/build/core/secure-fs.d.ts +67 -0
  65. package/build/core/secure-fs.d.ts.map +1 -0
  66. package/build/core/secure-fs.js +143 -0
  67. package/build/core/spawn-safe.d.ts +55 -0
  68. package/build/core/spawn-safe.d.ts.map +1 -0
  69. package/build/core/spawn-safe.js +146 -0
  70. package/build/core/sudo-guard.d.ts +145 -0
  71. package/build/core/sudo-guard.d.ts.map +1 -0
  72. package/build/core/sudo-guard.js +349 -0
  73. package/build/core/sudo-session.d.ts +100 -0
  74. package/build/core/sudo-session.d.ts.map +1 -0
  75. package/build/core/sudo-session.js +319 -0
  76. package/build/core/tool-dependencies.d.ts +61 -0
  77. package/build/core/tool-dependencies.d.ts.map +1 -0
  78. package/build/core/tool-dependencies.js +571 -0
  79. package/build/core/tool-registry.d.ts +111 -0
  80. package/build/core/tool-registry.d.ts.map +1 -0
  81. package/build/core/tool-registry.js +656 -0
  82. package/build/core/tool-wrapper.d.ts +73 -0
  83. package/build/core/tool-wrapper.d.ts.map +1 -0
  84. package/build/core/tool-wrapper.js +296 -0
  85. package/build/index.d.ts +3 -0
  86. package/build/index.d.ts.map +1 -0
  87. package/build/index.js +247 -0
  88. package/build/tools/access-control.d.ts +9 -0
  89. package/build/tools/access-control.d.ts.map +1 -0
  90. package/build/tools/access-control.js +1818 -0
  91. package/build/tools/api-security.d.ts +12 -0
  92. package/build/tools/api-security.d.ts.map +1 -0
  93. package/build/tools/api-security.js +901 -0
  94. package/build/tools/app-hardening.d.ts +11 -0
  95. package/build/tools/app-hardening.d.ts.map +1 -0
  96. package/build/tools/app-hardening.js +768 -0
  97. package/build/tools/backup.d.ts +8 -0
  98. package/build/tools/backup.d.ts.map +1 -0
  99. package/build/tools/backup.js +381 -0
  100. package/build/tools/cloud-security.d.ts +17 -0
  101. package/build/tools/cloud-security.d.ts.map +1 -0
  102. package/build/tools/cloud-security.js +739 -0
  103. package/build/tools/compliance.d.ts +10 -0
  104. package/build/tools/compliance.d.ts.map +1 -0
  105. package/build/tools/compliance.js +1225 -0
  106. package/build/tools/container-security.d.ts +14 -0
  107. package/build/tools/container-security.d.ts.map +1 -0
  108. package/build/tools/container-security.js +788 -0
  109. package/build/tools/deception.d.ts +13 -0
  110. package/build/tools/deception.d.ts.map +1 -0
  111. package/build/tools/deception.js +763 -0
  112. package/build/tools/dns-security.d.ts +93 -0
  113. package/build/tools/dns-security.d.ts.map +1 -0
  114. package/build/tools/dns-security.js +745 -0
  115. package/build/tools/drift-detection.d.ts +8 -0
  116. package/build/tools/drift-detection.d.ts.map +1 -0
  117. package/build/tools/drift-detection.js +326 -0
  118. package/build/tools/ebpf-security.d.ts +15 -0
  119. package/build/tools/ebpf-security.d.ts.map +1 -0
  120. package/build/tools/ebpf-security.js +294 -0
  121. package/build/tools/encryption.d.ts +9 -0
  122. package/build/tools/encryption.d.ts.map +1 -0
  123. package/build/tools/encryption.js +1667 -0
  124. package/build/tools/firewall.d.ts +9 -0
  125. package/build/tools/firewall.d.ts.map +1 -0
  126. package/build/tools/firewall.js +1398 -0
  127. package/build/tools/hardening.d.ts +10 -0
  128. package/build/tools/hardening.d.ts.map +1 -0
  129. package/build/tools/hardening.js +2654 -0
  130. package/build/tools/ids.d.ts +9 -0
  131. package/build/tools/ids.d.ts.map +1 -0
  132. package/build/tools/ids.js +624 -0
  133. package/build/tools/incident-response.d.ts +10 -0
  134. package/build/tools/incident-response.d.ts.map +1 -0
  135. package/build/tools/incident-response.js +1180 -0
  136. package/build/tools/logging.d.ts +12 -0
  137. package/build/tools/logging.d.ts.map +1 -0
  138. package/build/tools/logging.js +454 -0
  139. package/build/tools/malware.d.ts +10 -0
  140. package/build/tools/malware.d.ts.map +1 -0
  141. package/build/tools/malware.js +532 -0
  142. package/build/tools/meta.d.ts +11 -0
  143. package/build/tools/meta.d.ts.map +1 -0
  144. package/build/tools/meta.js +2278 -0
  145. package/build/tools/network-defense.d.ts +12 -0
  146. package/build/tools/network-defense.d.ts.map +1 -0
  147. package/build/tools/network-defense.js +760 -0
  148. package/build/tools/patch-management.d.ts +3 -0
  149. package/build/tools/patch-management.d.ts.map +1 -0
  150. package/build/tools/patch-management.js +708 -0
  151. package/build/tools/process-security.d.ts +12 -0
  152. package/build/tools/process-security.d.ts.map +1 -0
  153. package/build/tools/process-security.js +784 -0
  154. package/build/tools/reporting.d.ts +11 -0
  155. package/build/tools/reporting.d.ts.map +1 -0
  156. package/build/tools/reporting.js +559 -0
  157. package/build/tools/secrets.d.ts +9 -0
  158. package/build/tools/secrets.d.ts.map +1 -0
  159. package/build/tools/secrets.js +596 -0
  160. package/build/tools/siem-integration.d.ts +18 -0
  161. package/build/tools/siem-integration.d.ts.map +1 -0
  162. package/build/tools/siem-integration.js +754 -0
  163. package/build/tools/sudo-management.d.ts +18 -0
  164. package/build/tools/sudo-management.d.ts.map +1 -0
  165. package/build/tools/sudo-management.js +737 -0
  166. package/build/tools/supply-chain-security.d.ts +8 -0
  167. package/build/tools/supply-chain-security.d.ts.map +1 -0
  168. package/build/tools/supply-chain-security.js +256 -0
  169. package/build/tools/threat-intel.d.ts +22 -0
  170. package/build/tools/threat-intel.d.ts.map +1 -0
  171. package/build/tools/threat-intel.js +749 -0
  172. package/build/tools/vulnerability-management.d.ts +11 -0
  173. package/build/tools/vulnerability-management.d.ts.map +1 -0
  174. package/build/tools/vulnerability-management.js +667 -0
  175. package/build/tools/waf.d.ts +12 -0
  176. package/build/tools/waf.d.ts.map +1 -0
  177. package/build/tools/waf.js +843 -0
  178. package/build/tools/wireless-security.d.ts +19 -0
  179. package/build/tools/wireless-security.d.ts.map +1 -0
  180. package/build/tools/wireless-security.js +826 -0
  181. package/build/tools/zero-trust-network.d.ts +8 -0
  182. package/build/tools/zero-trust-network.d.ts.map +1 -0
  183. package/build/tools/zero-trust-network.js +367 -0
  184. package/docs/SAFEGUARDS.md +518 -0
  185. package/docs/TOOLS-REFERENCE.md +665 -0
  186. package/package.json +87 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Vulnerability management tools for Kali Defense MCP Server.
3
+ *
4
+ * Registers 1 tool: vuln_manage (actions: scan_system, scan_web, track, prioritize, remediation_plan)
5
+ *
6
+ * Provides vulnerability scanning, tracking, prioritization, and remediation planning
7
+ * using nmap, nikto, and searchsploit.
8
+ */
9
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ export declare function registerVulnerabilityManagementTools(server: McpServer): void;
11
+ //# sourceMappingURL=vulnerability-management.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vulnerability-management.d.ts","sourceRoot":"","sources":["../../src/tools/vulnerability-management.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4UpE,wBAAgB,oCAAoC,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuf5E"}
@@ -0,0 +1,667 @@
1
+ /**
2
+ * Vulnerability management tools for Kali Defense MCP Server.
3
+ *
4
+ * Registers 1 tool: vuln_manage (actions: scan_system, scan_web, track, prioritize, remediation_plan)
5
+ *
6
+ * Provides vulnerability scanning, tracking, prioritization, and remediation planning
7
+ * using nmap, nikto, and searchsploit.
8
+ */
9
+ import { z } from "zod";
10
+ import { spawnSafe } from "../core/spawn-safe.js";
11
+ import { secureWriteFileSync } from "../core/secure-fs.js";
12
+ import { createTextContent, createErrorContent, formatToolOutput, } from "../core/parsers.js";
13
+ import { existsSync, readFileSync } from "node:fs";
14
+ // ── Constants ──────────────────────────────────────────────────────────────────
15
+ const VULN_TRACKER_PATH = "/var/lib/kali-defense/vuln-tracker.json";
16
+ /**
17
+ * Run a command via spawnSafe and collect output as a promise.
18
+ * Handles errors gracefully — returns error info instead of throwing.
19
+ */
20
+ async function runCommand(command, args, timeoutMs = 60_000) {
21
+ return new Promise((resolve) => {
22
+ let child;
23
+ try {
24
+ child = spawnSafe(command, args);
25
+ }
26
+ catch (err) {
27
+ const msg = err instanceof Error ? err.message : String(err);
28
+ resolve({ stdout: "", stderr: msg, exitCode: -1 });
29
+ return;
30
+ }
31
+ let stdout = "";
32
+ let stderr = "";
33
+ let resolved = false;
34
+ const timer = setTimeout(() => {
35
+ if (!resolved) {
36
+ resolved = true;
37
+ child.kill("SIGTERM");
38
+ resolve({ stdout, stderr: stderr + "\n[TIMEOUT]", exitCode: -1 });
39
+ }
40
+ }, timeoutMs);
41
+ child.stdout?.on("data", (data) => {
42
+ stdout += data.toString();
43
+ });
44
+ child.stderr?.on("data", (data) => {
45
+ stderr += data.toString();
46
+ });
47
+ child.on("close", (code) => {
48
+ if (!resolved) {
49
+ resolved = true;
50
+ clearTimeout(timer);
51
+ resolve({ stdout, stderr, exitCode: code ?? -1 });
52
+ }
53
+ });
54
+ child.on("error", (err) => {
55
+ if (!resolved) {
56
+ resolved = true;
57
+ clearTimeout(timer);
58
+ resolve({ stdout, stderr: err.message, exitCode: -1 });
59
+ }
60
+ });
61
+ });
62
+ }
63
+ /**
64
+ * Load the vulnerability tracker database from disk.
65
+ */
66
+ function loadTracker() {
67
+ if (!existsSync(VULN_TRACKER_PATH)) {
68
+ return { vulnerabilities: [], last_updated: new Date().toISOString() };
69
+ }
70
+ try {
71
+ const content = readFileSync(VULN_TRACKER_PATH, "utf-8");
72
+ return JSON.parse(content);
73
+ }
74
+ catch {
75
+ return { vulnerabilities: [], last_updated: new Date().toISOString() };
76
+ }
77
+ }
78
+ /**
79
+ * Save the vulnerability tracker database to disk using secure file ops.
80
+ */
81
+ function saveTracker(data) {
82
+ data.last_updated = new Date().toISOString();
83
+ secureWriteFileSync(VULN_TRACKER_PATH, JSON.stringify(data, null, 2), "utf-8");
84
+ }
85
+ /**
86
+ * Parse nmap text output to extract vulnerability findings.
87
+ */
88
+ function parseNmapOutput(output) {
89
+ const results = [];
90
+ const lines = output.split("\n");
91
+ let currentPort = "";
92
+ let currentService = "";
93
+ let currentVersion = "";
94
+ let currentVulns = [];
95
+ for (const line of lines) {
96
+ // Match port lines like "22/tcp open ssh OpenSSH 8.9p1"
97
+ const portMatch = line.match(/^(\d+\/\w+)\s+open\s+(\S+)\s*(.*)/);
98
+ if (portMatch) {
99
+ if (currentPort) {
100
+ results.push({
101
+ port: currentPort,
102
+ service: currentService,
103
+ version: currentVersion,
104
+ vulnerabilities: currentVulns,
105
+ });
106
+ }
107
+ currentPort = portMatch[1];
108
+ currentService = portMatch[2];
109
+ currentVersion = portMatch[3]?.trim() || "";
110
+ currentVulns = [];
111
+ continue;
112
+ }
113
+ // Match CVE references
114
+ const cveMatch = line.match(/(CVE-\d{4}-\d{4,})/);
115
+ if (cveMatch && currentPort) {
116
+ const severity = line.toLowerCase().includes("critical")
117
+ ? "critical"
118
+ : line.toLowerCase().includes("high")
119
+ ? "high"
120
+ : line.toLowerCase().includes("medium")
121
+ ? "medium"
122
+ : "unknown";
123
+ currentVulns.push({
124
+ id: cveMatch[1],
125
+ title: line.trim(),
126
+ severity,
127
+ });
128
+ }
129
+ // Match VULNERABLE state from NSE scripts
130
+ const vulnMatch = line.match(/^\|\s+State:\s+VULNERABLE/i);
131
+ if (vulnMatch && currentPort) {
132
+ if (currentVulns.length === 0) {
133
+ currentVulns.push({
134
+ id: "NMAP-VULN",
135
+ title: "Vulnerability detected by NSE script",
136
+ severity: "medium",
137
+ });
138
+ }
139
+ }
140
+ }
141
+ // Push last port entry
142
+ if (currentPort) {
143
+ results.push({
144
+ port: currentPort,
145
+ service: currentService,
146
+ version: currentVersion,
147
+ vulnerabilities: currentVulns,
148
+ });
149
+ }
150
+ return results;
151
+ }
152
+ /**
153
+ * Parse nikto text output to extract findings.
154
+ */
155
+ function parseNiktoOutput(output) {
156
+ const findings = [];
157
+ const lines = output.split("\n");
158
+ for (const line of lines) {
159
+ // Match OSVDB entries like "+ OSVDB-1234: /path: description"
160
+ const osvdbMatch = line.match(/\+\s+(OSVDB-\d+):\s+(\S+):\s+(.*)/);
161
+ if (osvdbMatch) {
162
+ findings.push({
163
+ id: osvdbMatch[1],
164
+ description: osvdbMatch[3].trim(),
165
+ path: osvdbMatch[2],
166
+ });
167
+ continue;
168
+ }
169
+ // Match general findings like "+ /path: description"
170
+ const generalMatch = line.match(/\+\s+(\/\S*):\s+(.*)/);
171
+ if (generalMatch) {
172
+ findings.push({
173
+ id: "NIKTO",
174
+ description: generalMatch[2].trim(),
175
+ path: generalMatch[1],
176
+ });
177
+ }
178
+ }
179
+ return findings;
180
+ }
181
+ /**
182
+ * Calculate priority score for a vulnerability.
183
+ * Higher score = higher priority.
184
+ */
185
+ function calculatePriorityScore(vuln) {
186
+ let score = 0;
187
+ // CVSS score contributes most (0-10 range, multiply by 10)
188
+ if (vuln.cvss_score != null) {
189
+ score += vuln.cvss_score * 10;
190
+ }
191
+ // Severity score
192
+ switch (vuln.severity) {
193
+ case "critical":
194
+ score += 40;
195
+ break;
196
+ case "high":
197
+ score += 30;
198
+ break;
199
+ case "medium":
200
+ score += 20;
201
+ break;
202
+ case "low":
203
+ score += 10;
204
+ break;
205
+ }
206
+ // Age factor — older vulns get higher priority
207
+ const ageMs = Date.now() - new Date(vuln.discovered_at).getTime();
208
+ const ageDays = ageMs / (1000 * 60 * 60 * 24);
209
+ score += Math.min(ageDays, 30); // Cap at 30 days of bonus
210
+ // Exploit available elevates priority
211
+ if (vuln.exploit_available) {
212
+ score += 25;
213
+ }
214
+ return Math.round(score * 100) / 100;
215
+ }
216
+ /**
217
+ * Get recommended action for a vulnerability.
218
+ */
219
+ function getRecommendedAction(vuln) {
220
+ if (vuln.exploit_available) {
221
+ return "URGENT: Exploit exists — apply patch immediately or implement workaround";
222
+ }
223
+ switch (vuln.severity) {
224
+ case "critical":
225
+ return "Apply vendor patch or upgrade immediately";
226
+ case "high":
227
+ return "Schedule patch within 7 days";
228
+ case "medium":
229
+ return "Schedule patch within 30 days";
230
+ case "low":
231
+ return "Address during next maintenance window";
232
+ default:
233
+ return "Investigate and assess impact";
234
+ }
235
+ }
236
+ /**
237
+ * Get specific remediation steps based on vulnerability data.
238
+ */
239
+ function getRemediationSteps(vuln) {
240
+ const steps = [];
241
+ // CVE-based remediation
242
+ if (vuln.vuln_id.startsWith("CVE-")) {
243
+ steps.push(`Check vendor advisory for ${vuln.vuln_id}`);
244
+ steps.push("Apply the latest security patch from your package manager");
245
+ }
246
+ // Service-based remediation
247
+ if (vuln.affected_service) {
248
+ steps.push(`Update ${vuln.affected_service} to the latest version`);
249
+ steps.push(`Review ${vuln.affected_service} configuration for security hardening`);
250
+ }
251
+ // General steps
252
+ if (steps.length === 0) {
253
+ steps.push("Review vulnerability details and vendor advisories");
254
+ steps.push("Apply available patches: sudo apt update && sudo apt upgrade");
255
+ steps.push("Verify fix with a follow-up scan");
256
+ }
257
+ return steps.join("; ");
258
+ }
259
+ // ── Registration entry point ───────────────────────────────────────────────
260
+ export function registerVulnerabilityManagementTools(server) {
261
+ server.tool("vuln_manage", "Vulnerability management: scan systems/web apps, track vulnerabilities, prioritize remediation, and generate remediation plans.", {
262
+ action: z
263
+ .enum(["scan_system", "scan_web", "track", "prioritize", "remediation_plan"])
264
+ .describe("Action: scan_system=nmap vuln scan, scan_web=nikto web scan, track=manage vuln tracker, prioritize=risk-based prioritization, remediation_plan=generate remediation plan"),
265
+ target: z
266
+ .string()
267
+ .optional()
268
+ .describe("IP/hostname/URL to scan (used with scan_system, scan_web)"),
269
+ port_range: z
270
+ .string()
271
+ .optional()
272
+ .default("1-1024")
273
+ .describe("Port range for scanning (used with scan_system, default 1-1024)"),
274
+ scan_type: z
275
+ .enum(["quick", "full", "stealth"])
276
+ .optional()
277
+ .default("quick")
278
+ .describe("Scan type (used with scan_system, default quick)"),
279
+ vuln_id: z
280
+ .string()
281
+ .optional()
282
+ .describe("Vulnerability ID for tracking (used with track)"),
283
+ severity: z
284
+ .string()
285
+ .optional()
286
+ .describe("Severity level for new vulnerability (used with track)"),
287
+ description: z
288
+ .string()
289
+ .optional()
290
+ .describe("Vulnerability description (used with track)"),
291
+ status: z
292
+ .enum(["open", "mitigated", "accepted", "false_positive"])
293
+ .optional()
294
+ .describe("Vulnerability status (used with track)"),
295
+ severity_filter: z
296
+ .enum(["critical", "high", "medium", "low", "all"])
297
+ .optional()
298
+ .default("all")
299
+ .describe("Severity filter for prioritization (used with prioritize, default all)"),
300
+ output_format: z
301
+ .enum(["text", "json"])
302
+ .optional()
303
+ .default("text")
304
+ .describe("Output format (default text)"),
305
+ }, async (params) => {
306
+ const { action } = params;
307
+ switch (action) {
308
+ case "scan_system": {
309
+ try {
310
+ const target = params.target || "127.0.0.1";
311
+ const scanType = params.scan_type || "quick";
312
+ const portRange = params.port_range || "1-1024";
313
+ // Build nmap arguments based on scan type
314
+ let nmapArgs;
315
+ switch (scanType) {
316
+ case "quick":
317
+ nmapArgs = ["-sV", "--script=vuln", "--top-ports", "100", target];
318
+ break;
319
+ case "full":
320
+ nmapArgs = ["-sV", "--script=vuln", "-p", portRange, target];
321
+ break;
322
+ case "stealth":
323
+ nmapArgs = ["-sS", "-sV", "--script=vuln", target];
324
+ break;
325
+ default:
326
+ nmapArgs = ["-sV", "--script=vuln", "--top-ports", "100", target];
327
+ }
328
+ const nmapResult = await runCommand("nmap", nmapArgs, 120_000);
329
+ if (nmapResult.exitCode === -1 && nmapResult.stderr.includes("not in allowlist")) {
330
+ return {
331
+ content: [createErrorContent("nmap is not installed or not in the command allowlist. Install with: sudo apt install nmap")],
332
+ isError: true,
333
+ };
334
+ }
335
+ // Parse nmap output
336
+ const parsedResults = parseNmapOutput(nmapResult.stdout);
337
+ // Run searchsploit against discovered service versions
338
+ const exploitResults = [];
339
+ for (const svcResult of parsedResults) {
340
+ if (svcResult.version) {
341
+ const searchsploitResult = await runCommand("searchsploit", ["--json", `${svcResult.service} ${svcResult.version}`], 30_000);
342
+ if (searchsploitResult.exitCode === 0 && searchsploitResult.stdout.trim()) {
343
+ try {
344
+ const exploitData = JSON.parse(searchsploitResult.stdout);
345
+ const exploits = (exploitData.RESULTS_EXPLOIT || [])
346
+ .slice(0, 5)
347
+ .map((e) => e.Title || e.Path);
348
+ if (exploits.length > 0) {
349
+ exploitResults.push({
350
+ service: `${svcResult.service} ${svcResult.version}`,
351
+ exploits,
352
+ });
353
+ }
354
+ }
355
+ catch {
356
+ // JSON parse failed — searchsploit may have returned non-JSON
357
+ }
358
+ }
359
+ }
360
+ }
361
+ const output = {
362
+ target,
363
+ scanType,
364
+ portRange: scanType === "full" ? portRange : undefined,
365
+ nmapExitCode: nmapResult.exitCode,
366
+ services: parsedResults,
367
+ totalVulnerabilities: parsedResults.reduce((acc, r) => acc + r.vulnerabilities.length, 0),
368
+ exploitSearch: exploitResults,
369
+ raw: nmapResult.stdout.slice(0, 5000),
370
+ };
371
+ if (params.output_format === "json") {
372
+ return { content: [formatToolOutput(output)] };
373
+ }
374
+ return {
375
+ content: [createTextContent(`Vulnerability Scan Results (${scanType}) — Target: ${target}\n\n` +
376
+ `Services Found: ${parsedResults.length}\n` +
377
+ `Vulnerabilities: ${output.totalVulnerabilities}\n` +
378
+ `Exploits Found: ${exploitResults.length}\n\n` +
379
+ nmapResult.stdout.slice(0, 5000) +
380
+ (exploitResults.length > 0
381
+ ? `\n\nKnown Exploits:\n${exploitResults.map((e) => ` ${e.service}: ${e.exploits.join(", ")}`).join("\n")}`
382
+ : ""))],
383
+ };
384
+ }
385
+ catch (err) {
386
+ const msg = err instanceof Error ? err.message : String(err);
387
+ return {
388
+ content: [createErrorContent(`System scan failed: ${msg}`)],
389
+ isError: true,
390
+ };
391
+ }
392
+ }
393
+ case "scan_web": {
394
+ try {
395
+ const target = params.target || "http://localhost";
396
+ const niktoResult = await runCommand("nikto", ["-h", target, "-Format", "txt"], 120_000);
397
+ if (niktoResult.exitCode === -1 && niktoResult.stderr.includes("not in allowlist")) {
398
+ return {
399
+ content: [createErrorContent("nikto is not installed or not in the command allowlist. Install with: sudo apt install nikto")],
400
+ isError: true,
401
+ };
402
+ }
403
+ const findings = parseNiktoOutput(niktoResult.stdout);
404
+ const output = {
405
+ target,
406
+ niktoExitCode: niktoResult.exitCode,
407
+ totalFindings: findings.length,
408
+ findings,
409
+ raw: niktoResult.stdout.slice(0, 5000),
410
+ };
411
+ if (params.output_format === "json") {
412
+ return { content: [formatToolOutput(output)] };
413
+ }
414
+ return {
415
+ content: [createTextContent(`Web Vulnerability Scan — Target: ${target}\n\n` +
416
+ `Findings: ${findings.length}\n\n` +
417
+ findings
418
+ .map((f) => ` [${f.id}] ${f.path}: ${f.description}`)
419
+ .join("\n") +
420
+ (niktoResult.stdout
421
+ ? `\n\nRaw Output:\n${niktoResult.stdout.slice(0, 5000)}`
422
+ : ""))],
423
+ };
424
+ }
425
+ catch (err) {
426
+ const msg = err instanceof Error ? err.message : String(err);
427
+ return {
428
+ content: [createErrorContent(`Web scan failed: ${msg}`)],
429
+ isError: true,
430
+ };
431
+ }
432
+ }
433
+ case "track": {
434
+ try {
435
+ const tracker = loadTracker();
436
+ // If vuln_id provided with status, update existing
437
+ if (params.vuln_id && params.status) {
438
+ const existing = tracker.vulnerabilities.find((v) => v.vuln_id === params.vuln_id);
439
+ if (existing) {
440
+ existing.status = params.status;
441
+ existing.updated_at = new Date().toISOString();
442
+ saveTracker(tracker);
443
+ return {
444
+ content: [formatToolOutput({
445
+ action: "updated",
446
+ vuln_id: params.vuln_id,
447
+ new_status: params.status,
448
+ vulnerability: existing,
449
+ })],
450
+ };
451
+ }
452
+ }
453
+ // If vuln_id provided with severity and description, add new
454
+ if (params.vuln_id && params.severity && params.description) {
455
+ const existingIdx = tracker.vulnerabilities.findIndex((v) => v.vuln_id === params.vuln_id);
456
+ if (existingIdx >= 0) {
457
+ return {
458
+ content: [createErrorContent(`Vulnerability ${params.vuln_id} already exists. Use status parameter to update.`)],
459
+ isError: true,
460
+ };
461
+ }
462
+ const newVuln = {
463
+ vuln_id: params.vuln_id,
464
+ severity: params.severity,
465
+ description: params.description,
466
+ status: params.status || "open",
467
+ discovered_at: new Date().toISOString(),
468
+ updated_at: new Date().toISOString(),
469
+ };
470
+ tracker.vulnerabilities.push(newVuln);
471
+ saveTracker(tracker);
472
+ return {
473
+ content: [formatToolOutput({
474
+ action: "added",
475
+ vulnerability: newVuln,
476
+ totalTracked: tracker.vulnerabilities.length,
477
+ })],
478
+ };
479
+ }
480
+ // If vuln_id provided alone, get details
481
+ if (params.vuln_id) {
482
+ const vuln = tracker.vulnerabilities.find((v) => v.vuln_id === params.vuln_id);
483
+ if (!vuln) {
484
+ return {
485
+ content: [createErrorContent(`Vulnerability ${params.vuln_id} not found in tracker.`)],
486
+ isError: true,
487
+ };
488
+ }
489
+ return { content: [formatToolOutput({ vulnerability: vuln })] };
490
+ }
491
+ // No vuln_id — list all tracked vulnerabilities
492
+ return {
493
+ content: [formatToolOutput({
494
+ totalTracked: tracker.vulnerabilities.length,
495
+ byStatus: {
496
+ open: tracker.vulnerabilities.filter((v) => v.status === "open").length,
497
+ mitigated: tracker.vulnerabilities.filter((v) => v.status === "mitigated").length,
498
+ accepted: tracker.vulnerabilities.filter((v) => v.status === "accepted").length,
499
+ false_positive: tracker.vulnerabilities.filter((v) => v.status === "false_positive").length,
500
+ },
501
+ vulnerabilities: tracker.vulnerabilities,
502
+ last_updated: tracker.last_updated,
503
+ })],
504
+ };
505
+ }
506
+ catch (err) {
507
+ const msg = err instanceof Error ? err.message : String(err);
508
+ return {
509
+ content: [createErrorContent(`Vulnerability tracking failed: ${msg}`)],
510
+ isError: true,
511
+ };
512
+ }
513
+ }
514
+ case "prioritize": {
515
+ try {
516
+ const tracker = loadTracker();
517
+ const severityFilter = params.severity_filter || "all";
518
+ // Filter by status (only open vulnerabilities)
519
+ let vulns = tracker.vulnerabilities.filter((v) => v.status === "open");
520
+ // Filter by severity
521
+ if (severityFilter !== "all") {
522
+ vulns = vulns.filter((v) => v.severity === severityFilter);
523
+ }
524
+ // Calculate priority scores and sort
525
+ const prioritized = vulns
526
+ .map((v) => ({
527
+ ...v,
528
+ priority_score: calculatePriorityScore(v),
529
+ recommended_action: getRecommendedAction(v),
530
+ }))
531
+ .sort((a, b) => b.priority_score - a.priority_score);
532
+ const output = {
533
+ filter: severityFilter,
534
+ totalOpen: vulns.length,
535
+ prioritized,
536
+ summary: {
537
+ critical: prioritized.filter((v) => v.severity === "critical").length,
538
+ high: prioritized.filter((v) => v.severity === "high").length,
539
+ medium: prioritized.filter((v) => v.severity === "medium").length,
540
+ low: prioritized.filter((v) => v.severity === "low").length,
541
+ withExploits: prioritized.filter((v) => v.exploit_available).length,
542
+ },
543
+ };
544
+ if (params.output_format === "json") {
545
+ return { content: [formatToolOutput(output)] };
546
+ }
547
+ return {
548
+ content: [createTextContent(`Vulnerability Prioritization (filter: ${severityFilter})\n\n` +
549
+ `Total Open: ${vulns.length}\n\n` +
550
+ prioritized
551
+ .map((v, i) => `${i + 1}. [${v.severity.toUpperCase()}] ${v.vuln_id} (score: ${v.priority_score})\n` +
552
+ ` ${v.description}\n` +
553
+ ` Action: ${v.recommended_action}` +
554
+ (v.exploit_available ? "\n ⚠ EXPLOIT AVAILABLE" : ""))
555
+ .join("\n\n"))],
556
+ };
557
+ }
558
+ catch (err) {
559
+ const msg = err instanceof Error ? err.message : String(err);
560
+ return {
561
+ content: [createErrorContent(`Prioritization failed: ${msg}`)],
562
+ isError: true,
563
+ };
564
+ }
565
+ }
566
+ case "remediation_plan": {
567
+ try {
568
+ const tracker = loadTracker();
569
+ const openVulns = tracker.vulnerabilities.filter((v) => v.status === "open");
570
+ // Group by urgency
571
+ const immediate = openVulns.filter((v) => (v.severity === "critical" || v.severity === "high") &&
572
+ v.exploit_available);
573
+ const shortTerm = openVulns.filter((v) => (v.severity === "high" && !v.exploit_available) ||
574
+ (v.severity === "medium" && v.exploit_available === true));
575
+ const mediumTerm = openVulns.filter((v) => v.severity === "medium" && !v.exploit_available);
576
+ const longTerm = openVulns.filter((v) => v.severity === "low");
577
+ const plan = {
578
+ generated_at: new Date().toISOString(),
579
+ total_open: openVulns.length,
580
+ immediate_action: {
581
+ description: "Critical/high severity with known exploits — patch immediately",
582
+ count: immediate.length,
583
+ vulnerabilities: immediate.map((v) => ({
584
+ vuln_id: v.vuln_id,
585
+ severity: v.severity,
586
+ description: v.description,
587
+ remediation: getRemediationSteps(v),
588
+ })),
589
+ },
590
+ short_term: {
591
+ description: "High severity without exploits, medium with exploits — patch within 7 days",
592
+ count: shortTerm.length,
593
+ vulnerabilities: shortTerm.map((v) => ({
594
+ vuln_id: v.vuln_id,
595
+ severity: v.severity,
596
+ description: v.description,
597
+ remediation: getRemediationSteps(v),
598
+ })),
599
+ },
600
+ medium_term: {
601
+ description: "Medium severity without exploits — patch within 30 days",
602
+ count: mediumTerm.length,
603
+ vulnerabilities: mediumTerm.map((v) => ({
604
+ vuln_id: v.vuln_id,
605
+ severity: v.severity,
606
+ description: v.description,
607
+ remediation: getRemediationSteps(v),
608
+ })),
609
+ },
610
+ long_term: {
611
+ description: "Low severity — patch during next maintenance window",
612
+ count: longTerm.length,
613
+ vulnerabilities: longTerm.map((v) => ({
614
+ vuln_id: v.vuln_id,
615
+ severity: v.severity,
616
+ description: v.description,
617
+ remediation: getRemediationSteps(v),
618
+ })),
619
+ },
620
+ };
621
+ if (params.output_format === "json") {
622
+ return { content: [formatToolOutput(plan)] };
623
+ }
624
+ let text = `Remediation Plan — Generated: ${plan.generated_at}\n`;
625
+ text += `Total Open Vulnerabilities: ${openVulns.length}\n\n`;
626
+ text += `═══ IMMEDIATE ACTION (${immediate.length}) ═══\n`;
627
+ text += `${plan.immediate_action.description}\n`;
628
+ for (const v of plan.immediate_action.vulnerabilities) {
629
+ text += ` • [${v.severity.toUpperCase()}] ${v.vuln_id}: ${v.description}\n`;
630
+ text += ` Remediation: ${v.remediation}\n`;
631
+ }
632
+ text += `\n═══ SHORT-TERM (${shortTerm.length}) ═══\n`;
633
+ text += `${plan.short_term.description}\n`;
634
+ for (const v of plan.short_term.vulnerabilities) {
635
+ text += ` • [${v.severity.toUpperCase()}] ${v.vuln_id}: ${v.description}\n`;
636
+ text += ` Remediation: ${v.remediation}\n`;
637
+ }
638
+ text += `\n═══ MEDIUM-TERM (${mediumTerm.length}) ═══\n`;
639
+ text += `${plan.medium_term.description}\n`;
640
+ for (const v of plan.medium_term.vulnerabilities) {
641
+ text += ` • [${v.severity.toUpperCase()}] ${v.vuln_id}: ${v.description}\n`;
642
+ text += ` Remediation: ${v.remediation}\n`;
643
+ }
644
+ text += `\n═══ LONG-TERM (${longTerm.length}) ═══\n`;
645
+ text += `${plan.long_term.description}\n`;
646
+ for (const v of plan.long_term.vulnerabilities) {
647
+ text += ` • [${v.severity.toUpperCase()}] ${v.vuln_id}: ${v.description}\n`;
648
+ text += ` Remediation: ${v.remediation}\n`;
649
+ }
650
+ return { content: [createTextContent(text)] };
651
+ }
652
+ catch (err) {
653
+ const msg = err instanceof Error ? err.message : String(err);
654
+ return {
655
+ content: [createErrorContent(`Remediation plan generation failed: ${msg}`)],
656
+ isError: true,
657
+ };
658
+ }
659
+ }
660
+ default:
661
+ return {
662
+ content: [createErrorContent(`Unknown action: ${action}`)],
663
+ isError: true,
664
+ };
665
+ }
666
+ });
667
+ }