defense-mcp-server 0.9.2 → 0.9.3

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 (69) hide show
  1. package/build/core/auto-installer.js +31 -31
  2. package/build/core/command-allowlist.js +1 -1
  3. package/build/core/dependency-validator.js +9 -9
  4. package/build/core/distro-adapter.d.ts +0 -5
  5. package/build/core/distro-adapter.d.ts.map +1 -1
  6. package/build/core/distro-adapter.js +0 -7
  7. package/build/core/distro.d.ts +0 -11
  8. package/build/core/distro.d.ts.map +1 -1
  9. package/build/core/distro.js +0 -48
  10. package/build/core/encrypted-state.d.ts +0 -7
  11. package/build/core/encrypted-state.d.ts.map +1 -1
  12. package/build/core/encrypted-state.js +0 -7
  13. package/build/core/logger.js +1 -1
  14. package/build/core/pam-utils.js +1 -1
  15. package/build/core/parsers.js +1 -1
  16. package/build/core/preflight.d.ts +4 -4
  17. package/build/core/preflight.js +13 -13
  18. package/build/core/progress.js +20 -20
  19. package/build/core/run-command.d.ts +14 -0
  20. package/build/core/run-command.d.ts.map +1 -0
  21. package/build/core/run-command.js +46 -0
  22. package/build/core/spawn-safe.d.ts +6 -6
  23. package/build/core/spawn-safe.d.ts.map +1 -1
  24. package/build/core/sudo-guard.js +4 -4
  25. package/build/core/third-party-installer.js +4 -4
  26. package/build/core/tool-wrapper.js +3 -3
  27. package/build/tools/access-control.js +6 -6
  28. package/build/tools/api-security.d.ts.map +1 -1
  29. package/build/tools/api-security.js +5 -51
  30. package/build/tools/app-hardening.d.ts.map +1 -1
  31. package/build/tools/app-hardening.js +23 -25
  32. package/build/tools/cloud-security.d.ts.map +1 -1
  33. package/build/tools/cloud-security.js +5 -51
  34. package/build/tools/compliance.d.ts.map +1 -1
  35. package/build/tools/compliance.js +9 -13
  36. package/build/tools/container-security.d.ts.map +1 -1
  37. package/build/tools/container-security.js +51 -52
  38. package/build/tools/deception.d.ts.map +1 -1
  39. package/build/tools/deception.js +8 -54
  40. package/build/tools/dns-security.d.ts.map +1 -1
  41. package/build/tools/dns-security.js +2 -48
  42. package/build/tools/encryption.d.ts.map +1 -1
  43. package/build/tools/encryption.js +86 -87
  44. package/build/tools/firewall.d.ts.map +1 -1
  45. package/build/tools/firewall.js +324 -30
  46. package/build/tools/hardening.d.ts.map +1 -1
  47. package/build/tools/hardening.js +12 -13
  48. package/build/tools/incident-response.d.ts.map +1 -1
  49. package/build/tools/incident-response.js +3 -3
  50. package/build/tools/logging.d.ts.map +1 -1
  51. package/build/tools/logging.js +17 -59
  52. package/build/tools/malware.js +2 -2
  53. package/build/tools/meta.d.ts.map +1 -1
  54. package/build/tools/meta.js +86 -165
  55. package/build/tools/network-defense.d.ts.map +1 -1
  56. package/build/tools/network-defense.js +3 -3
  57. package/build/tools/patch-management.js +8 -8
  58. package/build/tools/process-security.d.ts.map +1 -1
  59. package/build/tools/process-security.js +38 -92
  60. package/build/tools/sudo-management.js +36 -36
  61. package/build/tools/threat-intel.d.ts.map +1 -1
  62. package/build/tools/threat-intel.js +2 -48
  63. package/build/tools/vulnerability-management.d.ts.map +1 -1
  64. package/build/tools/vulnerability-management.js +3 -49
  65. package/build/tools/waf.d.ts.map +1 -1
  66. package/build/tools/waf.js +47 -93
  67. package/build/tools/wireless-security.d.ts.map +1 -1
  68. package/build/tools/wireless-security.js +9 -55
  69. package/package.json +4 -2
@@ -454,8 +454,8 @@ export function registerAppHardeningTools(server) {
454
454
  case "audit": {
455
455
  try {
456
456
  const sections = [];
457
- sections.push("🔍 Application Security Audit");
458
- sections.push("=".repeat(55));
457
+ sections.push("Application Security Audit");
458
+ sections.push("");
459
459
  const apps = await detectRunningApps();
460
460
  if (apps.length === 0) {
461
461
  sections.push("\nNo known applications detected.");
@@ -467,9 +467,7 @@ export function registerAppHardeningTools(server) {
467
467
  apps.sort((a, b) => riskOrder[a.profile.riskLevel] - riskOrder[b.profile.riskLevel]);
468
468
  let totalRisks = 0;
469
469
  for (const app of apps) {
470
- const riskIcon = app.profile.riskLevel === "critical" ? "⛔" :
471
- app.profile.riskLevel === "high" ? "🔴" : app.profile.riskLevel === "medium" ? "🟡" : "🟢";
472
- sections.push(`── ${riskIcon} ${app.profile.name} ──`);
470
+ sections.push(`── ${app.profile.name} ──`);
473
471
  sections.push(` Category: ${app.profile.category}`);
474
472
  sections.push(` Risk Level: ${app.profile.riskLevel.toUpperCase()}`);
475
473
  sections.push(` Running as: ${app.user}`);
@@ -480,17 +478,17 @@ export function registerAppHardeningTools(server) {
480
478
  sections.push(` Listening Ports:`);
481
479
  for (const lp of app.listenPorts) {
482
480
  const external = !lp.address.includes("127.0.0.1") && !lp.address.includes("::1");
483
- sections.push(` ${lp.protocol}/${lp.port} on ${lp.address} [${external ? "⚠️ EXTERNAL" : "localhost"}]`);
481
+ sections.push(` ${lp.protocol}/${lp.port} on ${lp.address} [${external ? "WARNING: EXTERNAL" : "localhost"}]`);
484
482
  }
485
483
  }
486
484
  sections.push(` Security Concerns:`);
487
485
  for (const concern of app.profile.securityConcerns) {
488
- sections.push(` ⚠️ ${concern}`);
486
+ sections.push(` WARNING: ${concern}`);
489
487
  totalRisks++;
490
488
  }
491
489
  sections.push(` Top Recommendations:`);
492
490
  for (const rec of app.profile.recommendations.slice(0, 3)) {
493
- sections.push(` 💡 ${rec}`);
491
+ sections.push(` ${rec}`);
494
492
  }
495
493
  if (app.profile.recommendations.length > 3) {
496
494
  sections.push(` ... +${app.profile.recommendations.length - 3} more (use action=recommend)`);
@@ -530,24 +528,24 @@ export function registerAppHardeningTools(server) {
530
528
  };
531
529
  }
532
530
  const sections = [];
533
- sections.push(`🛡️ Hardening Guide: ${profile.name}`);
534
- sections.push("=".repeat(55));
531
+ sections.push(`Hardening Guide: ${profile.name}`);
532
+ sections.push("");
535
533
  sections.push(`Category: ${profile.category} | Risk: ${profile.riskLevel.toUpperCase()}`);
536
534
  sections.push("\n── Security Concerns ──");
537
535
  for (const concern of profile.securityConcerns) {
538
- sections.push(` ⚠️ ${concern}`);
536
+ sections.push(` WARNING: ${concern}`);
539
537
  }
540
538
  sections.push("\n── Network Hardening ──");
541
539
  if (profile.requiredPorts.length > 0) {
542
540
  sections.push(" Ports that MUST remain open (core functionality):");
543
541
  for (const p of profile.requiredPorts) {
544
- sections.push(` ${p.protocol}/${p.port} — ${p.purpose}`);
542
+ sections.push(` ${p.protocol}/${p.port} — ${p.purpose}`);
545
543
  }
546
544
  }
547
545
  if (profile.localhostOnlyPorts.length > 0) {
548
546
  sections.push(" Ports to restrict to localhost/LAN:");
549
547
  for (const p of profile.localhostOnlyPorts) {
550
- sections.push(` 🔒 ${p.protocol}/${p.port} — ${p.purpose}`);
548
+ sections.push(` ${p.protocol}/${p.port} — ${p.purpose}`);
551
549
  }
552
550
  }
553
551
  sections.push(" Firewall strategy:");
@@ -571,11 +569,11 @@ export function registerAppHardeningTools(server) {
571
569
  sections.push("\n── Filesystem Permissions ──");
572
570
  sections.push(" Writable paths (required for operation):");
573
571
  for (const p of profile.writablePaths) {
574
- sections.push(` 📝 ${p}`);
572
+ sections.push(` ${p}`);
575
573
  }
576
574
  sections.push(" Read-only paths:");
577
575
  for (const p of profile.readablePaths) {
578
- sections.push(` 📖 ${p}`);
576
+ sections.push(` ${p}`);
579
577
  }
580
578
  return { content: [createTextContent(sections.join("\n"))] };
581
579
  }
@@ -600,8 +598,8 @@ export function registerAppHardeningTools(server) {
600
598
  }
601
599
  const effectiveDryRun = dry_run ?? getConfig().dryRun;
602
600
  const sections = [];
603
- sections.push(`🔥 Firewall Rules for ${profile.name}`);
604
- sections.push("=".repeat(55));
601
+ sections.push(`Firewall Rules for ${profile.name}`);
602
+ sections.push("");
605
603
  sections.push(`LAN CIDR: ${lan_cidr}`);
606
604
  sections.push(effectiveDryRun ? "\n[DRY RUN] Rules that would be applied:\n" : "\nApplying rules:\n");
607
605
  const rules = [];
@@ -632,7 +630,7 @@ export function registerAppHardeningTools(server) {
632
630
  else
633
631
  failed++;
634
632
  }
635
- sections.push(`\n✅ Applied ${applied} rules, ${failed} failed`);
633
+ sections.push(`\nApplied ${applied} rules, ${failed} failed`);
636
634
  }
637
635
  sections.push("\n── Additional Recommendations ──");
638
636
  sections.push(" • Consider using nftables for more granular control");
@@ -690,10 +688,10 @@ export function registerAppHardeningTools(server) {
690
688
  }
691
689
  }
692
690
  const sections = [];
693
- sections.push(`🔒 Systemd Hardening: ${profile.name}`);
694
- sections.push("=".repeat(55));
691
+ sections.push(`Systemd Hardening: ${profile.name}`);
692
+ sections.push("");
695
693
  if (!svcName) {
696
- sections.push(`\n⚠️ No running systemd service found for ${profile.name}.`);
694
+ sections.push(`\nWARNING: No running systemd service found for ${profile.name}.`);
697
695
  sections.push("Provide service_name manually if the service uses a different name.");
698
696
  sections.push("\nRecommended override content for when the service is configured:\n");
699
697
  }
@@ -726,12 +724,12 @@ export function registerAppHardeningTools(server) {
726
724
  });
727
725
  if (writeResult.exitCode === 0) {
728
726
  await executeCommand({ toolName: "app_hardening", command: "sudo", args: ["systemctl", "daemon-reload"], timeout: 10000 });
729
- sections.push(`\n✅ Override written to ${overridePath}`);
730
- sections.push("systemd daemon reloaded");
731
- sections.push(`\n⚠️ Restart the service to apply: sudo systemctl restart ${svcName}`);
727
+ sections.push(`\nOverride written to ${overridePath}`);
728
+ sections.push("systemd daemon reloaded");
729
+ sections.push(`\nRestart the service to apply: sudo systemctl restart ${svcName}`);
732
730
  }
733
731
  else {
734
- sections.push(`\n❌ Failed to write override: ${writeResult.stderr}`);
732
+ sections.push(`\nFailed to write override: ${writeResult.stderr}`);
735
733
  }
736
734
  }
737
735
  sections.push("\n── What These Directives Do ──");
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-security.d.ts","sourceRoot":"","sources":["../../src/tools/cloud-security.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuGpE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKpD;AA4fD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6RlE"}
1
+ {"version":3,"file":"cloud-security.d.ts","sourceRoot":"","sources":["../../src/tools/cloud-security.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyCpE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKpD;AA4fD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6RlE"}
@@ -8,7 +8,7 @@
8
8
  * exposure checking, storage audit, and IMDS security assessment for AWS/GCP/Azure.
9
9
  */
10
10
  import { z } from "zod";
11
- import { spawnSafe } from "../core/spawn-safe.js";
11
+ import { runCommand } from "../core/run-command.js";
12
12
  import { createTextContent, createErrorContent, formatToolOutput, } from "../core/parsers.js";
13
13
  import { existsSync } from "node:fs";
14
14
  /** Sensitive environment variable names for cloud credentials */
@@ -30,53 +30,7 @@ const CREDENTIAL_FILE_PATHS = [
30
30
  { provider: "gcp", path: "~/.config/gcloud/application_default_credentials.json" },
31
31
  { provider: "azure", path: "~/.azure/accessTokens.json" },
32
32
  ];
33
- /**
34
- * Run a command via spawnSafe and collect output as a promise.
35
- * Handles errors gracefully — returns error info instead of throwing.
36
- */
37
- async function runCommand(command, args, timeoutMs = 30_000) {
38
- return new Promise((resolve) => {
39
- let child;
40
- try {
41
- child = spawnSafe(command, args);
42
- }
43
- catch (err) {
44
- const msg = err instanceof Error ? err.message : String(err);
45
- resolve({ stdout: "", stderr: msg, exitCode: -1 });
46
- return;
47
- }
48
- let stdout = "";
49
- let stderr = "";
50
- let resolved = false;
51
- const timer = setTimeout(() => {
52
- if (!resolved) {
53
- resolved = true;
54
- child.kill("SIGTERM");
55
- resolve({ stdout, stderr: stderr + "\n[TIMEOUT]", exitCode: -1 });
56
- }
57
- }, timeoutMs);
58
- child.stdout?.on("data", (data) => {
59
- stdout += data.toString();
60
- });
61
- child.stderr?.on("data", (data) => {
62
- stderr += data.toString();
63
- });
64
- child.on("close", (code) => {
65
- if (!resolved) {
66
- resolved = true;
67
- clearTimeout(timer);
68
- resolve({ stdout, stderr, exitCode: code ?? -1 });
69
- }
70
- });
71
- child.on("error", (err) => {
72
- if (!resolved) {
73
- resolved = true;
74
- clearTimeout(timer);
75
- resolve({ stdout, stderr: err.message, exitCode: -1 });
76
- }
77
- });
78
- });
79
- }
33
+ // ── Helpers ────────────────────────────────────────────────────────────────────
80
34
  // ── Credential masking ─────────────────────────────────────────────────────────
81
35
  /**
82
36
  * Mask a credential value, showing first 4 chars + asterisks.
@@ -611,7 +565,7 @@ export function registerCloudSecurityTools(server) {
611
565
  text += "Credential Files:\n";
612
566
  for (const file of creds.credentialFiles) {
613
567
  const status = file.exists
614
- ? `EXISTS (permissions: ${file.permissions || "unknown"})${file.permWarning ? ` ${file.permWarning}` : ""}`
568
+ ? `EXISTS (permissions: ${file.permissions || "unknown"})${file.permWarning ? ` WARNING: ${file.permWarning}` : ""}`
615
569
  : "not found";
616
570
  text += ` • ${file.path}: ${status}\n`;
617
571
  }
@@ -706,10 +660,10 @@ export function registerCloudSecurityTools(server) {
706
660
  return { content: [formatToolOutput(output)] };
707
661
  }
708
662
  let text = "Cloud Security — IMDS Security Check\n\n";
709
- text += `IMDSv1 (unauthenticated): ${imds.v1Accessible ? "ACCESSIBLE " : "not accessible "}\n`;
663
+ text += `IMDSv1 (unauthenticated): ${imds.v1Accessible ? "ACCESSIBLE WARNING" : "not accessible OK"}\n`;
710
664
  text += `IMDSv2 (token-based): ${imds.v2Accessible ? "accessible" : "not accessible"}\n`;
711
665
  text += `IMDSv2 Token Endpoint: ${imds.v2TokenWorks ? "working" : "not working"}\n`;
712
- text += `Iptables IMDS Rules: ${imds.iptablesBlocked ? "BLOCKED " : imds.iptablesRules.length > 0 ? "rules found" : "no rules"}\n`;
666
+ text += `Iptables IMDS Rules: ${imds.iptablesBlocked ? "BLOCKED OK" : imds.iptablesRules.length > 0 ? "rules found" : "no rules"}\n`;
713
667
  text += `Hop Limit: ${imds.hopLimit}\n`;
714
668
  text += `\nSeverity: ${imds.severity}\n`;
715
669
  text += `Security Score: ${imds.securityScore}/100\n`;
@@ -1 +1 @@
1
- {"version":3,"file":"compliance.d.ts","sourceRoot":"","sources":["../../src/tools/compliance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsdpE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0iC/D"}
1
+ {"version":3,"file":"compliance.d.ts","sourceRoot":"","sources":["../../src/tools/compliance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsdpE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsiC/D"}
@@ -14,7 +14,7 @@ import { generateDurationBanner, generateTimingSummary, startTiming, } from "../
14
14
  import { logChange, createChangeEntry } from "../core/changelog.js";
15
15
  import { getDistroAdapter } from "../core/distro-adapter.js";
16
16
  import { sanitizeArgs } from "../core/sanitizer.js";
17
- import { readFileSync } from "node:fs";
17
+ import { readFileSync, statSync } from "node:fs";
18
18
  import { loadPolicy, evaluatePolicy, getBuiltinPolicies, } from "../core/policy-engine.js";
19
19
  async function runCisCheck(command, args, id, title, level, expectPattern) {
20
20
  try {
@@ -668,7 +668,7 @@ export function registerComplianceTools(server) {
668
668
  }
669
669
  function filePermCheckLocal(filePath, maxPerm) {
670
670
  try {
671
- const { statSync } = require("node:fs");
671
+ // statSync imported at module level
672
672
  const stat = statSync(filePath);
673
673
  const mode = (stat.mode & 0o777).toString(8);
674
674
  return { passed: parseInt(mode, 8) <= parseInt(maxPerm, 8), detail: `${filePath}: ${mode} (max: ${maxPerm})` };
@@ -943,21 +943,17 @@ export function registerComplianceTools(server) {
943
943
  for (const section of report.sections) {
944
944
  md += `## ${section.name}\n\n`;
945
945
  md += `**Score:** ${section.score}/100\n\n`;
946
- md += `\`\`\`json\n${JSON.stringify(section.details, null, 2)}\n\`\`\`\n\n`;
946
+ md += `\`\`\`json\n${JSON.stringify(section.details)}\n\`\`\`\n\n`;
947
947
  }
948
948
  return { content: [createTextContent(md)] };
949
949
  }
950
950
  // Text format
951
- let text = `${"=".repeat(60)}\n`;
952
- text += ` COMPLIANCE REPORT\n`;
953
- text += ` Generated: ${report.timestamp}\n`;
954
- text += ` Overall Score: ${report.overallScore}/100\n`;
955
- text += `${"=".repeat(60)}\n\n`;
951
+ let text = `COMPLIANCE REPORT\n`;
952
+ text += `Generated: ${report.timestamp}\n`;
953
+ text += `Overall Score: ${report.overallScore}/100\n\n`;
956
954
  for (const section of report.sections) {
957
- text += `${"─".repeat(50)}\n`;
958
- text += ` ${section.name} — Score: ${section.score}/100\n`;
959
- text += `${"─".repeat(50)}\n`;
960
- text += `${JSON.stringify(section.details, null, 2)}\n\n`;
955
+ text += `${section.name} — Score: ${section.score}/100\n`;
956
+ text += `${JSON.stringify(section.details)}\n\n`;
961
957
  }
962
958
  return { content: [createTextContent(text)] };
963
959
  }
@@ -981,7 +977,7 @@ export function registerComplianceTools(server) {
981
977
  const currentUser = process.env.USER || process.env.LOGNAME;
982
978
  if (currentUser && currentUser !== "root" && !allowed_users.includes(currentUser)) {
983
979
  allowed_users = [...allowed_users, currentUser];
984
- changes.push(`⚠️ Auto-included current user '${currentUser}' in allowed_users to prevent self-lockout`);
980
+ changes.push(`WARNING: Auto-included current user '${currentUser}' in allowed_users to prevent self-lockout`);
985
981
  }
986
982
  // Validate usernames
987
983
  for (const user of allowed_users) {
@@ -1 +1 @@
1
- {"version":3,"file":"container-security.d.ts","sourceRoot":"","sources":["../../src/tools/container-security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwBpE,eAAO,MAAM,yBAAyB,aAyBpC,CAAC;AAIH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6vBtE"}
1
+ {"version":3,"file":"container-security.d.ts","sourceRoot":"","sources":["../../src/tools/container-security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwBpE,eAAO,MAAM,yBAAyB,aAyBpC,CAAC;AAIH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4vBtE"}