defense-mcp-server 0.9.3 → 0.9.5

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 (135) hide show
  1. package/build/index.js +98 -76
  2. package/package.json +2 -2
  3. package/build/core/auto-installer.d.ts +0 -102
  4. package/build/core/auto-installer.d.ts.map +0 -1
  5. package/build/core/backup-manager.d.ts +0 -63
  6. package/build/core/backup-manager.d.ts.map +0 -1
  7. package/build/core/changelog.d.ts +0 -119
  8. package/build/core/changelog.d.ts.map +0 -1
  9. package/build/core/command-allowlist.d.ts +0 -129
  10. package/build/core/command-allowlist.d.ts.map +0 -1
  11. package/build/core/config.d.ts +0 -107
  12. package/build/core/config.d.ts.map +0 -1
  13. package/build/core/dependency-validator.d.ts +0 -106
  14. package/build/core/dependency-validator.d.ts.map +0 -1
  15. package/build/core/distro-adapter.d.ts +0 -172
  16. package/build/core/distro-adapter.d.ts.map +0 -1
  17. package/build/core/distro.d.ts +0 -57
  18. package/build/core/distro.d.ts.map +0 -1
  19. package/build/core/encrypted-state.d.ts +0 -69
  20. package/build/core/encrypted-state.d.ts.map +0 -1
  21. package/build/core/executor.d.ts +0 -65
  22. package/build/core/executor.d.ts.map +0 -1
  23. package/build/core/installer.d.ts +0 -129
  24. package/build/core/installer.d.ts.map +0 -1
  25. package/build/core/logger.d.ts +0 -118
  26. package/build/core/logger.d.ts.map +0 -1
  27. package/build/core/metrics.d.ts +0 -74
  28. package/build/core/metrics.d.ts.map +0 -1
  29. package/build/core/metrics.js +0 -97
  30. package/build/core/output-redactor.d.ts +0 -26
  31. package/build/core/output-redactor.d.ts.map +0 -1
  32. package/build/core/pam-utils.d.ts +0 -356
  33. package/build/core/pam-utils.d.ts.map +0 -1
  34. package/build/core/parsers.d.ts +0 -191
  35. package/build/core/parsers.d.ts.map +0 -1
  36. package/build/core/policy-engine.d.ts +0 -170
  37. package/build/core/policy-engine.d.ts.map +0 -1
  38. package/build/core/preflight.d.ts +0 -157
  39. package/build/core/preflight.d.ts.map +0 -1
  40. package/build/core/privilege-manager.d.ts +0 -108
  41. package/build/core/privilege-manager.d.ts.map +0 -1
  42. package/build/core/progress.d.ts +0 -99
  43. package/build/core/progress.d.ts.map +0 -1
  44. package/build/core/rate-limiter.d.ts +0 -101
  45. package/build/core/rate-limiter.d.ts.map +0 -1
  46. package/build/core/rollback.d.ts +0 -73
  47. package/build/core/rollback.d.ts.map +0 -1
  48. package/build/core/run-command.d.ts +0 -14
  49. package/build/core/run-command.d.ts.map +0 -1
  50. package/build/core/safeguards.d.ts +0 -58
  51. package/build/core/safeguards.d.ts.map +0 -1
  52. package/build/core/sanitizer.d.ts +0 -118
  53. package/build/core/sanitizer.d.ts.map +0 -1
  54. package/build/core/secure-fs.d.ts +0 -67
  55. package/build/core/secure-fs.d.ts.map +0 -1
  56. package/build/core/spawn-safe.d.ts +0 -55
  57. package/build/core/spawn-safe.d.ts.map +0 -1
  58. package/build/core/sudo-guard.d.ts +0 -167
  59. package/build/core/sudo-guard.d.ts.map +0 -1
  60. package/build/core/sudo-session.d.ts +0 -143
  61. package/build/core/sudo-session.d.ts.map +0 -1
  62. package/build/core/third-party-installer.d.ts +0 -58
  63. package/build/core/third-party-installer.d.ts.map +0 -1
  64. package/build/core/third-party-manifest.d.ts +0 -48
  65. package/build/core/third-party-manifest.d.ts.map +0 -1
  66. package/build/core/tool-annotations.d.ts +0 -13
  67. package/build/core/tool-annotations.d.ts.map +0 -1
  68. package/build/core/tool-dependencies.d.ts +0 -60
  69. package/build/core/tool-dependencies.d.ts.map +0 -1
  70. package/build/core/tool-durations.d.ts +0 -71
  71. package/build/core/tool-durations.d.ts.map +0 -1
  72. package/build/core/tool-registry.d.ts +0 -112
  73. package/build/core/tool-registry.d.ts.map +0 -1
  74. package/build/core/tool-wrapper.d.ts +0 -73
  75. package/build/core/tool-wrapper.d.ts.map +0 -1
  76. package/build/index.d.ts +0 -3
  77. package/build/index.d.ts.map +0 -1
  78. package/build/tools/access-control.d.ts +0 -11
  79. package/build/tools/access-control.d.ts.map +0 -1
  80. package/build/tools/api-security.d.ts +0 -12
  81. package/build/tools/api-security.d.ts.map +0 -1
  82. package/build/tools/app-hardening.d.ts +0 -11
  83. package/build/tools/app-hardening.d.ts.map +0 -1
  84. package/build/tools/backup.d.ts +0 -8
  85. package/build/tools/backup.d.ts.map +0 -1
  86. package/build/tools/cloud-security.d.ts +0 -17
  87. package/build/tools/cloud-security.d.ts.map +0 -1
  88. package/build/tools/compliance.d.ts +0 -11
  89. package/build/tools/compliance.d.ts.map +0 -1
  90. package/build/tools/container-security.d.ts +0 -14
  91. package/build/tools/container-security.d.ts.map +0 -1
  92. package/build/tools/deception.d.ts +0 -13
  93. package/build/tools/deception.d.ts.map +0 -1
  94. package/build/tools/dns-security.d.ts +0 -93
  95. package/build/tools/dns-security.d.ts.map +0 -1
  96. package/build/tools/ebpf-security.d.ts +0 -15
  97. package/build/tools/ebpf-security.d.ts.map +0 -1
  98. package/build/tools/encryption.d.ts +0 -12
  99. package/build/tools/encryption.d.ts.map +0 -1
  100. package/build/tools/firewall.d.ts +0 -9
  101. package/build/tools/firewall.d.ts.map +0 -1
  102. package/build/tools/hardening.d.ts +0 -8
  103. package/build/tools/hardening.d.ts.map +0 -1
  104. package/build/tools/incident-response.d.ts +0 -11
  105. package/build/tools/incident-response.d.ts.map +0 -1
  106. package/build/tools/integrity.d.ts +0 -15
  107. package/build/tools/integrity.d.ts.map +0 -1
  108. package/build/tools/logging.d.ts +0 -21
  109. package/build/tools/logging.d.ts.map +0 -1
  110. package/build/tools/malware.d.ts +0 -10
  111. package/build/tools/malware.d.ts.map +0 -1
  112. package/build/tools/meta.d.ts +0 -13
  113. package/build/tools/meta.d.ts.map +0 -1
  114. package/build/tools/network-defense.d.ts +0 -11
  115. package/build/tools/network-defense.d.ts.map +0 -1
  116. package/build/tools/patch-management.d.ts +0 -3
  117. package/build/tools/patch-management.d.ts.map +0 -1
  118. package/build/tools/process-security.d.ts +0 -12
  119. package/build/tools/process-security.d.ts.map +0 -1
  120. package/build/tools/secrets.d.ts +0 -8
  121. package/build/tools/secrets.d.ts.map +0 -1
  122. package/build/tools/sudo-management.d.ts +0 -17
  123. package/build/tools/sudo-management.d.ts.map +0 -1
  124. package/build/tools/supply-chain-security.d.ts +0 -8
  125. package/build/tools/supply-chain-security.d.ts.map +0 -1
  126. package/build/tools/threat-intel.d.ts +0 -22
  127. package/build/tools/threat-intel.d.ts.map +0 -1
  128. package/build/tools/vulnerability-management.d.ts +0 -11
  129. package/build/tools/vulnerability-management.d.ts.map +0 -1
  130. package/build/tools/waf.d.ts +0 -12
  131. package/build/tools/waf.d.ts.map +0 -1
  132. package/build/tools/wireless-security.d.ts +0 -19
  133. package/build/tools/wireless-security.d.ts.map +0 -1
  134. package/build/tools/zero-trust-network.d.ts +0 -8
  135. package/build/tools/zero-trust-network.d.ts.map +0 -1
package/build/index.js CHANGED
@@ -104,10 +104,6 @@ process.on("unhandledRejection", (reason) => {
104
104
  });
105
105
  // ── Main entry point ─────────────────────────────────────────────────────────
106
106
  async function main() {
107
- const server = new McpServer({
108
- name: "defense-mcp-server",
109
- version: VERSION,
110
- });
111
107
  // ── Phase 1: Dependency Validation & Auto-Install ────────────────────────
112
108
  //
113
109
  // Before registering tools, validate that all required system binaries
@@ -216,66 +212,79 @@ async function main() {
216
212
  catch {
217
213
  // Non-fatal — third-party check failure must not block startup
218
214
  }
219
- // Wrap server with pre-flight middleware
220
- const wrappedServer = createPreflightServer(server);
221
- // ── Phase 2: Register all defensive tool modules (with error isolation) ──
222
- let registered = 0;
223
- let failed = 0;
224
- const failedModules = [];
225
- function safeRegister(name, fn) {
226
- try {
227
- fn(wrappedServer);
228
- registered++;
229
- }
230
- catch (err) {
231
- failed++;
232
- failedModules.push(name);
233
- console.error(`[startup] Failed to register ${name} tools: ${err instanceof Error ? err.message : err}`);
215
+ // ── Phase 2: Tool registration ────────────────────────────────────────────
216
+ //
217
+ // registerAllTools() creates a fresh McpServer, wraps it with pre-flight
218
+ // middleware, and registers every tool module. For stdio we call it once;
219
+ // for HTTP we call it per session so each client gets its own instance
220
+ // (the MCP SDK only allows one transport per McpServer).
221
+ function registerAllTools() {
222
+ const srv = new McpServer({
223
+ name: "defense-mcp-server",
224
+ version: VERSION,
225
+ });
226
+ const wrapped = createPreflightServer(srv);
227
+ let registered = 0;
228
+ let failed = 0;
229
+ const failedModules = [];
230
+ function safeRegister(name, fn) {
231
+ try {
232
+ fn(wrapped);
233
+ registered++;
234
+ }
235
+ catch (err) {
236
+ failed++;
237
+ failedModules.push(name);
238
+ console.error(`[startup] ⚠ Failed to register ${name} tools: ${err instanceof Error ? err.message : err}`);
239
+ }
234
240
  }
241
+ // Sudo privilege management (must be registered first — prerequisite for other tools)
242
+ safeRegister("sudo-management", registerSudoManagementTools);
243
+ // Original tool modules
244
+ safeRegister("firewall", registerFirewallTools);
245
+ safeRegister("hardening", registerHardeningTools);
246
+ safeRegister("integrity", registerIntegrityTools);
247
+ safeRegister("logging", registerLoggingTools);
248
+ safeRegister("network-defense", registerNetworkDefenseTools);
249
+ safeRegister("compliance", registerComplianceTools);
250
+ safeRegister("malware", registerMalwareTools);
251
+ safeRegister("backup", registerBackupTools);
252
+ safeRegister("access-control", registerAccessControlTools);
253
+ safeRegister("encryption", registerEncryptionTools);
254
+ safeRegister("container-security", registerContainerSecurityTools);
255
+ safeRegister("meta", registerMetaTools);
256
+ safeRegister("patch-management", registerPatchManagementTools);
257
+ safeRegister("secrets", registerSecretsTools);
258
+ safeRegister("incident-response", registerIncidentResponseTools);
259
+ // New tool modules
260
+ safeRegister("supply-chain-security", registerSupplyChainSecurityTools);
261
+ safeRegister("zero-trust-network", registerZeroTrustNetworkTools);
262
+ safeRegister("ebpf-security", registerEbpfSecurityTools);
263
+ safeRegister("app-hardening", registerAppHardeningTools);
264
+ // v0.6.0 tool modules
265
+ safeRegister("api-security", registerApiSecurityTools);
266
+ safeRegister("cloud-security", registerCloudSecurityTools);
267
+ safeRegister("deception", registerDeceptionTools);
268
+ safeRegister("dns-security", registerDnsSecurityTools);
269
+ safeRegister("process-security", registerProcessSecurityTools);
270
+ safeRegister("threat-intel", registerThreatIntelTools);
271
+ safeRegister("vulnerability-management", registerVulnerabilityManagementTools);
272
+ safeRegister("waf", registerWafTools);
273
+ safeRegister("wireless-security", registerWirelessSecurityTools);
274
+ return { server: srv, registered, failed, failedModules };
235
275
  }
236
- // Sudo privilege management (must be registered first — prerequisite for other tools)
237
- safeRegister("sudo-management", registerSudoManagementTools);
238
- // Original tool modules
239
- safeRegister("firewall", registerFirewallTools);
240
- safeRegister("hardening", registerHardeningTools);
241
- safeRegister("integrity", registerIntegrityTools);
242
- safeRegister("logging", registerLoggingTools);
243
- safeRegister("network-defense", registerNetworkDefenseTools);
244
- safeRegister("compliance", registerComplianceTools);
245
- safeRegister("malware", registerMalwareTools);
246
- safeRegister("backup", registerBackupTools);
247
- safeRegister("access-control", registerAccessControlTools);
248
- safeRegister("encryption", registerEncryptionTools);
249
- safeRegister("container-security", registerContainerSecurityTools);
250
- safeRegister("meta", registerMetaTools);
251
- safeRegister("patch-management", registerPatchManagementTools);
252
- safeRegister("secrets", registerSecretsTools);
253
- safeRegister("incident-response", registerIncidentResponseTools);
254
- // New tool modules
255
- safeRegister("supply-chain-security", registerSupplyChainSecurityTools);
256
- safeRegister("zero-trust-network", registerZeroTrustNetworkTools);
257
- safeRegister("ebpf-security", registerEbpfSecurityTools);
258
- safeRegister("app-hardening", registerAppHardeningTools);
259
- // v0.6.0 tool modules
260
- safeRegister("api-security", registerApiSecurityTools);
261
- safeRegister("cloud-security", registerCloudSecurityTools);
262
- safeRegister("deception", registerDeceptionTools);
263
- safeRegister("dns-security", registerDnsSecurityTools);
264
- safeRegister("process-security", registerProcessSecurityTools);
265
- safeRegister("threat-intel", registerThreatIntelTools);
266
- safeRegister("vulnerability-management", registerVulnerabilityManagementTools);
267
- safeRegister("waf", registerWafTools);
268
- safeRegister("wireless-security", registerWirelessSecurityTools);
269
- // Fail hard if no modules loaded at all
270
- if (registered === 0) {
276
+ // Validate that tool registration works (fail-fast on startup)
277
+ const initial = registerAllTools();
278
+ if (initial.registered === 0) {
271
279
  throw new Error("No tool modules loaded — server cannot start");
272
280
  }
273
281
  // ── Phase 3: Connect transport ───────────────────────────────────────────
274
282
  const transportMode = process.env.MCP_TRANSPORT ?? "stdio";
275
- const registrationMsg = `Registered ${registered} tool modules with consolidated defensive security tools` +
276
- `${failed > 0 ? ` (${failed} failed: ${failedModules.join(", ")})` : ""}`;
283
+ const registrationMsg = `Registered ${initial.registered} tool modules with consolidated defensive security tools` +
284
+ `${initial.failed > 0 ? ` (${initial.failed} failed: ${initial.failedModules.join(", ")})` : ""}`;
277
285
  if (transportMode === "http") {
278
286
  const port = parseInt(process.env.MCP_PORT ?? "3100", 10);
287
+ const apiKey = process.env.MCP_API_KEY ?? "";
279
288
  // Server card for Smithery discovery
280
289
  const serverCard = {
281
290
  serverInfo: {
@@ -283,7 +292,7 @@ async function main() {
283
292
  version: VERSION,
284
293
  description: "31 defensive security tools (250+ actions) for Linux system hardening, compliance, and threat detection",
285
294
  },
286
- authentication: { required: false },
295
+ authentication: { required: !!apiKey },
287
296
  tools: [
288
297
  { name: "access_control", description: "Access control: SSH, PAM, sudo, user audit, password policy, shell restriction" },
289
298
  { name: "api_security", description: "API security: local API discovery, auth audit, rate limiting, TLS verify, CORS check" },
@@ -320,63 +329,74 @@ async function main() {
320
329
  resources: [],
321
330
  prompts: [],
322
331
  };
323
- // Track active transports by session ID
332
+ // Track active sessions: each gets its own McpServer + transport pair
324
333
  const sessions = new Map();
325
334
  const httpServer = createServer(async (req, res) => {
326
335
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
327
336
  const pathname = url.pathname;
328
- // CORS for Smithery Gateway
337
+ // CORS headers
329
338
  res.setHeader("Access-Control-Allow-Origin", "*");
330
339
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
331
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, mcp-session-id, smithery-*");
340
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, mcp-session-id, smithery-*");
332
341
  res.setHeader("Access-Control-Expose-Headers", "mcp-session-id");
333
342
  if (req.method === "OPTIONS") {
334
343
  res.writeHead(204).end();
335
344
  return;
336
345
  }
337
- // Health check
346
+ // Health check (unauthenticated)
338
347
  if (req.method === "GET" && pathname === "/health") {
339
348
  res.writeHead(200, { "Content-Type": "application/json" });
340
- res.end(JSON.stringify({ status: "ok", version: VERSION, tools: registered }));
349
+ res.end(JSON.stringify({ status: "ok", version: VERSION, tools: initial.registered }));
341
350
  return;
342
351
  }
343
- // Smithery server card
352
+ // Smithery server card (unauthenticated)
344
353
  if (req.method === "GET" && pathname === "/.well-known/mcp/server-card.json") {
345
354
  res.writeHead(200, { "Content-Type": "application/json" });
346
355
  res.end(JSON.stringify(serverCard));
347
356
  return;
348
357
  }
358
+ // API key authentication (when MCP_API_KEY is set)
359
+ if (apiKey) {
360
+ const authHeader = req.headers["authorization"] ?? "";
361
+ const provided = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : "";
362
+ if (provided !== apiKey) {
363
+ res.writeHead(401, { "Content-Type": "application/json" });
364
+ res.end(JSON.stringify({ error: "Unauthorized", message: "Valid Bearer token required" }));
365
+ return;
366
+ }
367
+ }
349
368
  // MCP Streamable HTTP endpoint
350
369
  if (pathname === "/mcp" || pathname === "/") {
351
370
  const sessionId = req.headers["mcp-session-id"];
352
371
  if (req.method === "GET" || req.method === "POST") {
353
- // Reuse existing session or create new one
354
- let transport = sessionId ? sessions.get(sessionId) : undefined;
355
- if (!transport) {
356
- transport = new StreamableHTTPServerTransport({
372
+ // Reuse existing session or create a new McpServer + transport pair
373
+ let session = sessionId ? sessions.get(sessionId) : undefined;
374
+ if (!session) {
375
+ const { server: sessionServer } = registerAllTools();
376
+ const transport = new StreamableHTTPServerTransport({
357
377
  sessionIdGenerator: () => crypto.randomUUID(),
358
378
  });
359
- await server.connect(transport);
360
- // Store session after first request so we can retrieve it by ID
379
+ await sessionServer.connect(transport);
380
+ session = { server: sessionServer, transport };
361
381
  transport.onclose = () => {
362
- const sid = [...sessions.entries()].find(([, t]) => t === transport)?.[0];
382
+ const sid = [...sessions.entries()].find(([, s]) => s.transport === transport)?.[0];
363
383
  if (sid)
364
384
  sessions.delete(sid);
365
385
  };
366
386
  }
367
- await transport.handleRequest(req, res);
387
+ await session.transport.handleRequest(req, res);
368
388
  // Capture session ID from response headers if new session
369
389
  if (!sessionId) {
370
390
  const newSid = res.getHeader("mcp-session-id");
371
- if (newSid && transport)
372
- sessions.set(newSid, transport);
391
+ if (newSid && session)
392
+ sessions.set(newSid, session);
373
393
  }
374
394
  return;
375
395
  }
376
396
  if (req.method === "DELETE") {
377
397
  if (sessionId && sessions.has(sessionId)) {
378
- const transport = sessions.get(sessionId);
379
- await transport.handleRequest(req, res);
398
+ const session = sessions.get(sessionId);
399
+ await session.transport.handleRequest(req, res);
380
400
  sessions.delete(sessionId);
381
401
  }
382
402
  else {
@@ -390,14 +410,16 @@ async function main() {
390
410
  httpServer.listen(port, () => {
391
411
  console.error(`Defense MCP Server v${VERSION} running on HTTP port ${port}`);
392
412
  console.error(registrationMsg);
413
+ console.error(`[startup] Authentication: ${apiKey ? "ENABLED (MCP_API_KEY)" : "DISABLED — set MCP_API_KEY to require Bearer auth"}`);
393
414
  console.error("[startup] MCP endpoint: http://0.0.0.0:" + port + "/mcp");
394
415
  console.error("[startup] Health check: http://0.0.0.0:" + port + "/health");
395
416
  console.error("[startup] Server card: http://0.0.0.0:" + port + "/.well-known/mcp/server-card.json");
396
417
  });
397
418
  }
398
419
  else {
420
+ // stdio mode: single server instance, single transport
399
421
  const transport = new StdioServerTransport();
400
- await server.connect(transport);
422
+ await initial.server.connect(transport);
401
423
  console.error(`Defense MCP Server v${VERSION} running on stdio`);
402
424
  console.error(registrationMsg);
403
425
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "defense-mcp-server",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "Defense MCP Server — 31 defensive security tools with 250+ actions for system hardening, compliance, and threat detection on Linux",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
@@ -8,7 +8,7 @@
8
8
  "defense-mcp-server": "build/index.js"
9
9
  },
10
10
  "files": [
11
- "build/",
11
+ "build/**/*.js",
12
12
  "README.md",
13
13
  "CHANGELOG.md",
14
14
  "LICENSE",
@@ -1,102 +0,0 @@
1
- /**
2
- * AutoInstaller — multi-package-manager automatic dependency resolver.
3
- *
4
- * Handles installation of missing dependencies across system package managers
5
- * (apt, dnf, yum, pacman, apk, zypper, brew), pip, and npm. This module is
6
- * part of the pre-flight validation pipeline and is invoked when
7
- * `DEFENSE_MCP_AUTO_INSTALL=true`.
8
- *
9
- * Design constraints:
10
- * - Uses `execFileSafe` from `spawn-safe.ts` (NOT the executor) to avoid
11
- * circular dependencies with `sudo-session`. spawn-safe enforces the
12
- * command allowlist and `shell: false` automatically.
13
- * - Every `execFileSafe` call is wrapped in try/catch — install failures
14
- * must NEVER crash the server.
15
- * - Logs exclusively to stderr (`console.error`) because the MCP server
16
- * uses stdio for JSON-RPC transport.
17
- *
18
- * @module auto-installer
19
- */
20
- import type { ToolManifest } from "./tool-registry.js";
21
- export interface InstallAttempt {
22
- dependency: string;
23
- type: "binary" | "python-module" | "npm-package" | "library" | "file";
24
- method: "system-package" | "pip" | "npm" | "cargo" | "go-install" | "binary-download" | "build-from-source" | "vendored" | "skipped";
25
- success: boolean;
26
- message: string;
27
- duration?: number;
28
- }
29
- export interface AutoInstallResult {
30
- attempted: InstallAttempt[];
31
- allResolved: boolean;
32
- unresolvedDependencies: string[];
33
- }
34
- /**
35
- * Validate that a package name contains only safe characters.
36
- * Allowed: alphanumeric, hyphens, dots, plus signs, colons (for arch qualifiers).
37
- * No shell metacharacters, no path separators, no spaces.
38
- * Max length: 128 characters.
39
- */
40
- export declare function validatePackageName(name: string): boolean;
41
- export declare class AutoInstaller {
42
- private static _instance;
43
- private distroCache;
44
- /** Get or create the singleton instance. */
45
- static instance(): AutoInstaller;
46
- /**
47
- * Reset the singleton (for testing).
48
- * @internal
49
- */
50
- static resetInstance(): void;
51
- /** Check if auto-install is enabled via config. */
52
- isEnabled(): boolean;
53
- /**
54
- * Resolve all missing dependencies for a tool manifest.
55
- *
56
- * If auto-install is disabled, returns all dependencies as unresolved
57
- * with method `'skipped'`.
58
- */
59
- resolveAll(manifest: ToolManifest, missingBinaries: string[], missingPython?: string[], missingNpm?: string[], missingLibraries?: string[]): Promise<AutoInstallResult>;
60
- /**
61
- * Install a system binary via the detected package manager.
62
- *
63
- * 1. Look up binary in DEFENSIVE_TOOLS for distro-specific package name
64
- * 2. If not found, try binary name directly as package name
65
- * 3. Verify with `which <binary>` after install
66
- */
67
- installBinary(binary: string): Promise<InstallAttempt>;
68
- /**
69
- * Install a Python module via pip.
70
- *
71
- * 1. Check if pip3 or pip exists
72
- * 2. Try user-site install first (no sudo)
73
- * 3. If that fails, try with sudo
74
- * 4. Verify with `python3 -c "import <module>"`
75
- */
76
- installPythonModule(module: string): Promise<InstallAttempt>;
77
- /**
78
- * Install an npm package globally.
79
- *
80
- * 1. Check if npm exists
81
- * 2. Run `npm install -g <package>` with sudo if needed
82
- * 3. Verify by checking if the package provides an expected binary
83
- */
84
- installNpmPackage(pkg: string): Promise<InstallAttempt>;
85
- /**
86
- * Install a system library (development headers).
87
- *
88
- * 1. Determine dev package name based on distro family
89
- * 2. Try installing the first candidate that works
90
- * 3. Verify with `ldconfig -p | grep <lib>` or `pkg-config --exists <lib>`
91
- */
92
- installLibrary(lib: string): Promise<InstallAttempt>;
93
- /**
94
- * Get (and cache) the detected distro info.
95
- */
96
- private getDistro;
97
- /**
98
- * Verify a library is available via ldconfig or pkg-config.
99
- */
100
- private verifyLibrary;
101
- }
102
- //# sourceMappingURL=auto-installer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auto-installer.d.ts","sourceRoot":"","sources":["../../src/core/auto-installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASvD,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,QAAQ,GAAG,eAAe,GAAG,aAAa,GAAG,SAAS,GAAG,MAAM,CAAC;IACtE,MAAM,EACF,gBAAgB,GAChB,KAAK,GACL,KAAK,GACL,OAAO,GACP,YAAY,GACZ,iBAAiB,GACjB,mBAAmB,GACnB,UAAU,GACV,SAAS,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC;AA0FD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAoOD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,SAAS,CAA8B;IACtD,OAAO,CAAC,WAAW,CAA2B;IAE9C,4CAA4C;IAC5C,MAAM,CAAC,QAAQ,IAAI,aAAa;IAahC;;;OAGG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAI5B,mDAAmD;IACnD,SAAS,IAAI,OAAO;IAIpB;;;;;OAKG;IACG,UAAU,CACd,QAAQ,EAAE,YAAY,EACtB,eAAe,EAAE,MAAM,EAAE,EACzB,aAAa,CAAC,EAAE,MAAM,EAAE,EACxB,UAAU,CAAC,EAAE,MAAM,EAAE,EACrB,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,iBAAiB,CAAC;IA6G7B;;;;;;OAMG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAsP5D;;;;;;;OAOG;IACG,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAgHlE;;;;;;OAMG;IACG,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA8G7D;;;;;;OAMG;IACG,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAwG1D;;OAEG;YACW,SAAS;IAOvB;;OAEG;IACH,OAAO,CAAC,aAAa;CAmBtB"}
@@ -1,63 +0,0 @@
1
- /**
2
- * BackupManager — manages file backups with manifest tracking.
3
- *
4
- * Backups are stored under ~/.defense-mcp/backups/ with timestamped filenames.
5
- * A manifest.json tracks all backups for listing and restore operations.
6
- */
7
- export interface BackupEntry {
8
- id: string;
9
- originalPath: string;
10
- backupPath: string;
11
- timestamp: string;
12
- sizeBytes: number;
13
- }
14
- export interface BackupManifest {
15
- version: 1;
16
- backups: BackupEntry[];
17
- }
18
- /**
19
- * Validate that a backup path is safe:
20
- * 1. No `..` traversal sequences
21
- * 2. Normalized via path.resolve()
22
- * 3. Resolved path is within the backup base directory
23
- * 4. Not a symlink (prevent symlink attacks)
24
- *
25
- * @param filePath The path to validate
26
- * @param baseDir The backup base directory that paths must stay within
27
- * @throws {Error} If the path fails validation
28
- */
29
- export declare function validateBackupPath(filePath: string, baseDir: string): void;
30
- export declare class BackupManager {
31
- private readonly backupDir;
32
- private readonly manifestPath;
33
- constructor(backupDir?: string);
34
- /** Ensure backup directory exists. */
35
- private ensureDir;
36
- /** Read manifest from disk with migration from old format. */
37
- private readManifest;
38
- /** Write manifest to disk. */
39
- private writeManifest;
40
- /**
41
- * Create a backup of a file (synchronous).
42
- * @returns The BackupEntry with id and backupPath.
43
- */
44
- backupSync(filePath: string): BackupEntry;
45
- /**
46
- * Create a backup of a file.
47
- * @returns The backup ID.
48
- */
49
- backup(filePath: string): Promise<string>;
50
- /**
51
- * Restore a file from backup by ID.
52
- */
53
- restore(backupId: string): Promise<void>;
54
- /**
55
- * List all backup entries.
56
- */
57
- listBackups(): Promise<BackupEntry[]>;
58
- /**
59
- * Remove backups older than the specified number of days.
60
- */
61
- pruneOldBackups(daysOld: number): Promise<void>;
62
- }
63
- //# sourceMappingURL=backup-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"backup-manager.d.ts","sourceRoot":"","sources":["../../src/core/backup-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgBH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAiC1E;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,SAAS,CAAC,EAAE,MAAM;IAK9B,sCAAsC;IACtC,OAAO,CAAC,SAAS;IAIjB,8DAA8D;IAC9D,OAAO,CAAC,YAAY;IAepB,8BAA8B;IAC9B,OAAO,CAAC,aAAa;IAKrB;;;OAGG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW;IAyCzC;;;OAGG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK/C;;OAEG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB9C;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAO3C;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAiCtD"}
@@ -1,119 +0,0 @@
1
- /**
2
- * A single changelog entry recording a defensive action taken.
3
- */
4
- export interface ChangeEntry {
5
- /** Unique identifier (UUID v4) */
6
- id: string;
7
- /** ISO 8601 timestamp */
8
- timestamp: string;
9
- /** Tool that performed the action */
10
- tool: string;
11
- /** Description of the action */
12
- action: string;
13
- /** Target of the action (file, service, etc.) */
14
- target: string;
15
- /** State before the change */
16
- before?: string;
17
- /** State after the change */
18
- after?: string;
19
- /** Path to backup file if one was created */
20
- backupPath?: string;
21
- /** Whether this was a dry-run (no actual changes) */
22
- dryRun: boolean;
23
- /** Whether the action succeeded */
24
- success: boolean;
25
- /** Error message if the action failed */
26
- error?: string;
27
- /** Command to undo this change */
28
- rollbackCommand?: string;
29
- /** OS username who made the change (auto-populated) */
30
- user?: string;
31
- /** MCP session identifier (if available) */
32
- sessionId?: string;
33
- /**
34
- * SHA-256 hash-chain value.
35
- *
36
- * For the first entry: SHA-256 of the entry's core fields with previousHash="genesis".
37
- * For subsequent entries: SHA-256 of the entry's core fields concatenated with
38
- * the previous entry's hash. This creates a tamper-evident chain — modifying or
39
- * deleting any entry breaks the chain, which is detectable via `verifyChangelog()`.
40
- *
41
- * Auto-populated by `logChange()`. Not present in legacy entries.
42
- */
43
- hash?: string;
44
- }
45
- /**
46
- * Versioned changelog state file format.
47
- * Old files stored a bare array; new files use this envelope.
48
- */
49
- export interface ChangelogState {
50
- version: 1;
51
- entries: ChangeEntry[];
52
- }
53
- /**
54
- * Compute the SHA-256 hash-chain value for a changelog entry.
55
- *
56
- * The hash is computed over the entry's immutable fields (id, timestamp, tool,
57
- * action, target, dryRun, success) concatenated with the previous entry's hash.
58
- * This creates a tamper-evident chain.
59
- *
60
- * @param entry - The entry to hash (hash field is excluded from the computation)
61
- * @param previousHash - Hash of the previous entry, or "genesis" for the first entry
62
- * @returns SHA-256 hex digest
63
- */
64
- export declare function computeEntryHash(entry: ChangeEntry, previousHash: string): string;
65
- /**
66
- * Verify the integrity of the changelog hash chain.
67
- *
68
- * Walks all entries with `hash` fields and checks that each hash matches
69
- * the recomputed value from the previous entry's hash. Legacy entries
70
- * without `hash` fields are skipped.
71
- *
72
- * @returns Object with `valid` boolean and details of any broken links
73
- */
74
- export declare function verifyChangelog(): {
75
- valid: boolean;
76
- totalEntries: number;
77
- hashedEntries: number;
78
- brokenLinks: Array<{
79
- index: number;
80
- entryId: string;
81
- expected: string;
82
- actual: string;
83
- }>;
84
- };
85
- /**
86
- * Creates a new ChangeEntry with auto-generated id and timestamp.
87
- */
88
- export declare function createChangeEntry(partial: Omit<ChangeEntry, "id" | "timestamp" | "user">): ChangeEntry;
89
- /**
90
- * Appends a change entry to the changelog JSON file.
91
- * Creates the file and parent directories if they don't exist.
92
- * Rotates old entries when the file exceeds MAX_CHANGELOG_ENTRIES.
93
- * Computes and attaches a hash-chain value for tamper evidence.
94
- * Fails silently (logs to stderr) to avoid disrupting tool execution.
95
- */
96
- export declare function logChange(entry: ChangeEntry): void;
97
- /**
98
- * Reads changelog entries, newest first.
99
- * Returns empty array on any error.
100
- *
101
- * @param limit Maximum number of entries to return (default: all)
102
- */
103
- export declare function getChangelog(limit?: number): ChangeEntry[];
104
- /**
105
- * Creates a backup copy of a file using the unified BackupManager.
106
- * The backup is tracked in the manifest at ~/.defense-mcp/backups/manifest.json.
107
- *
108
- * @param filePath Absolute path to the file to back up
109
- * @returns Path to the backup file
110
- */
111
- export declare function backupFile(filePath: string): string;
112
- /**
113
- * Restores a file from a backup.
114
- *
115
- * @param backupPath Path to the backup file
116
- * @param originalPath Path to restore the file to
117
- */
118
- export declare function restoreFile(backupPath: string, originalPath: string): void;
119
- //# sourceMappingURL=changelog.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/core/changelog.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,MAAM,EAAE,OAAO,CAAC;IAChB,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAcjF;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1F,CAuCA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,WAAW,GAAG,MAAM,CAAC,GACtD,WAAW,CAOb;AA2BD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAiClD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAmB1D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAU1E"}