defense-mcp-server 0.9.2 → 0.9.4

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 (170) 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.js +0 -7
  5. package/build/core/distro.js +0 -48
  6. package/build/core/encrypted-state.js +0 -7
  7. package/build/core/logger.js +1 -1
  8. package/build/core/pam-utils.js +1 -1
  9. package/build/core/parsers.js +1 -1
  10. package/build/core/preflight.js +13 -13
  11. package/build/core/progress.js +20 -20
  12. package/build/core/run-command.js +46 -0
  13. package/build/core/sudo-guard.js +4 -4
  14. package/build/core/third-party-installer.js +4 -4
  15. package/build/core/tool-wrapper.js +3 -3
  16. package/build/tools/access-control.js +6 -6
  17. package/build/tools/api-security.js +5 -51
  18. package/build/tools/app-hardening.js +23 -25
  19. package/build/tools/cloud-security.js +5 -51
  20. package/build/tools/compliance.js +9 -13
  21. package/build/tools/container-security.js +51 -52
  22. package/build/tools/deception.js +8 -54
  23. package/build/tools/dns-security.js +2 -48
  24. package/build/tools/encryption.js +86 -87
  25. package/build/tools/firewall.js +324 -30
  26. package/build/tools/hardening.js +12 -13
  27. package/build/tools/incident-response.js +3 -3
  28. package/build/tools/logging.js +17 -59
  29. package/build/tools/malware.js +2 -2
  30. package/build/tools/meta.js +86 -165
  31. package/build/tools/network-defense.js +3 -3
  32. package/build/tools/patch-management.js +8 -8
  33. package/build/tools/process-security.js +38 -92
  34. package/build/tools/sudo-management.js +36 -36
  35. package/build/tools/threat-intel.js +2 -48
  36. package/build/tools/vulnerability-management.js +3 -49
  37. package/build/tools/waf.js +47 -93
  38. package/build/tools/wireless-security.js +9 -55
  39. package/package.json +5 -3
  40. package/build/core/auto-installer.d.ts +0 -102
  41. package/build/core/auto-installer.d.ts.map +0 -1
  42. package/build/core/backup-manager.d.ts +0 -63
  43. package/build/core/backup-manager.d.ts.map +0 -1
  44. package/build/core/changelog.d.ts +0 -119
  45. package/build/core/changelog.d.ts.map +0 -1
  46. package/build/core/command-allowlist.d.ts +0 -129
  47. package/build/core/command-allowlist.d.ts.map +0 -1
  48. package/build/core/config.d.ts +0 -107
  49. package/build/core/config.d.ts.map +0 -1
  50. package/build/core/dependency-validator.d.ts +0 -106
  51. package/build/core/dependency-validator.d.ts.map +0 -1
  52. package/build/core/distro-adapter.d.ts +0 -177
  53. package/build/core/distro-adapter.d.ts.map +0 -1
  54. package/build/core/distro.d.ts +0 -68
  55. package/build/core/distro.d.ts.map +0 -1
  56. package/build/core/encrypted-state.d.ts +0 -76
  57. package/build/core/encrypted-state.d.ts.map +0 -1
  58. package/build/core/executor.d.ts +0 -65
  59. package/build/core/executor.d.ts.map +0 -1
  60. package/build/core/installer.d.ts +0 -129
  61. package/build/core/installer.d.ts.map +0 -1
  62. package/build/core/logger.d.ts +0 -118
  63. package/build/core/logger.d.ts.map +0 -1
  64. package/build/core/metrics.d.ts +0 -74
  65. package/build/core/metrics.d.ts.map +0 -1
  66. package/build/core/metrics.js +0 -97
  67. package/build/core/output-redactor.d.ts +0 -26
  68. package/build/core/output-redactor.d.ts.map +0 -1
  69. package/build/core/pam-utils.d.ts +0 -356
  70. package/build/core/pam-utils.d.ts.map +0 -1
  71. package/build/core/parsers.d.ts +0 -191
  72. package/build/core/parsers.d.ts.map +0 -1
  73. package/build/core/policy-engine.d.ts +0 -170
  74. package/build/core/policy-engine.d.ts.map +0 -1
  75. package/build/core/preflight.d.ts +0 -157
  76. package/build/core/preflight.d.ts.map +0 -1
  77. package/build/core/privilege-manager.d.ts +0 -108
  78. package/build/core/privilege-manager.d.ts.map +0 -1
  79. package/build/core/progress.d.ts +0 -99
  80. package/build/core/progress.d.ts.map +0 -1
  81. package/build/core/rate-limiter.d.ts +0 -101
  82. package/build/core/rate-limiter.d.ts.map +0 -1
  83. package/build/core/rollback.d.ts +0 -73
  84. package/build/core/rollback.d.ts.map +0 -1
  85. package/build/core/safeguards.d.ts +0 -58
  86. package/build/core/safeguards.d.ts.map +0 -1
  87. package/build/core/sanitizer.d.ts +0 -118
  88. package/build/core/sanitizer.d.ts.map +0 -1
  89. package/build/core/secure-fs.d.ts +0 -67
  90. package/build/core/secure-fs.d.ts.map +0 -1
  91. package/build/core/spawn-safe.d.ts +0 -55
  92. package/build/core/spawn-safe.d.ts.map +0 -1
  93. package/build/core/sudo-guard.d.ts +0 -167
  94. package/build/core/sudo-guard.d.ts.map +0 -1
  95. package/build/core/sudo-session.d.ts +0 -143
  96. package/build/core/sudo-session.d.ts.map +0 -1
  97. package/build/core/third-party-installer.d.ts +0 -58
  98. package/build/core/third-party-installer.d.ts.map +0 -1
  99. package/build/core/third-party-manifest.d.ts +0 -48
  100. package/build/core/third-party-manifest.d.ts.map +0 -1
  101. package/build/core/tool-annotations.d.ts +0 -13
  102. package/build/core/tool-annotations.d.ts.map +0 -1
  103. package/build/core/tool-dependencies.d.ts +0 -60
  104. package/build/core/tool-dependencies.d.ts.map +0 -1
  105. package/build/core/tool-durations.d.ts +0 -71
  106. package/build/core/tool-durations.d.ts.map +0 -1
  107. package/build/core/tool-registry.d.ts +0 -112
  108. package/build/core/tool-registry.d.ts.map +0 -1
  109. package/build/core/tool-wrapper.d.ts +0 -73
  110. package/build/core/tool-wrapper.d.ts.map +0 -1
  111. package/build/index.d.ts +0 -3
  112. package/build/index.d.ts.map +0 -1
  113. package/build/tools/access-control.d.ts +0 -11
  114. package/build/tools/access-control.d.ts.map +0 -1
  115. package/build/tools/api-security.d.ts +0 -12
  116. package/build/tools/api-security.d.ts.map +0 -1
  117. package/build/tools/app-hardening.d.ts +0 -11
  118. package/build/tools/app-hardening.d.ts.map +0 -1
  119. package/build/tools/backup.d.ts +0 -8
  120. package/build/tools/backup.d.ts.map +0 -1
  121. package/build/tools/cloud-security.d.ts +0 -17
  122. package/build/tools/cloud-security.d.ts.map +0 -1
  123. package/build/tools/compliance.d.ts +0 -11
  124. package/build/tools/compliance.d.ts.map +0 -1
  125. package/build/tools/container-security.d.ts +0 -14
  126. package/build/tools/container-security.d.ts.map +0 -1
  127. package/build/tools/deception.d.ts +0 -13
  128. package/build/tools/deception.d.ts.map +0 -1
  129. package/build/tools/dns-security.d.ts +0 -93
  130. package/build/tools/dns-security.d.ts.map +0 -1
  131. package/build/tools/ebpf-security.d.ts +0 -15
  132. package/build/tools/ebpf-security.d.ts.map +0 -1
  133. package/build/tools/encryption.d.ts +0 -12
  134. package/build/tools/encryption.d.ts.map +0 -1
  135. package/build/tools/firewall.d.ts +0 -9
  136. package/build/tools/firewall.d.ts.map +0 -1
  137. package/build/tools/hardening.d.ts +0 -8
  138. package/build/tools/hardening.d.ts.map +0 -1
  139. package/build/tools/incident-response.d.ts +0 -11
  140. package/build/tools/incident-response.d.ts.map +0 -1
  141. package/build/tools/integrity.d.ts +0 -15
  142. package/build/tools/integrity.d.ts.map +0 -1
  143. package/build/tools/logging.d.ts +0 -21
  144. package/build/tools/logging.d.ts.map +0 -1
  145. package/build/tools/malware.d.ts +0 -10
  146. package/build/tools/malware.d.ts.map +0 -1
  147. package/build/tools/meta.d.ts +0 -13
  148. package/build/tools/meta.d.ts.map +0 -1
  149. package/build/tools/network-defense.d.ts +0 -11
  150. package/build/tools/network-defense.d.ts.map +0 -1
  151. package/build/tools/patch-management.d.ts +0 -3
  152. package/build/tools/patch-management.d.ts.map +0 -1
  153. package/build/tools/process-security.d.ts +0 -12
  154. package/build/tools/process-security.d.ts.map +0 -1
  155. package/build/tools/secrets.d.ts +0 -8
  156. package/build/tools/secrets.d.ts.map +0 -1
  157. package/build/tools/sudo-management.d.ts +0 -17
  158. package/build/tools/sudo-management.d.ts.map +0 -1
  159. package/build/tools/supply-chain-security.d.ts +0 -8
  160. package/build/tools/supply-chain-security.d.ts.map +0 -1
  161. package/build/tools/threat-intel.d.ts +0 -22
  162. package/build/tools/threat-intel.d.ts.map +0 -1
  163. package/build/tools/vulnerability-management.d.ts +0 -11
  164. package/build/tools/vulnerability-management.d.ts.map +0 -1
  165. package/build/tools/waf.d.ts +0 -12
  166. package/build/tools/waf.d.ts.map +0 -1
  167. package/build/tools/wireless-security.d.ts +0 -19
  168. package/build/tools/wireless-security.d.ts.map +0 -1
  169. package/build/tools/zero-trust-network.d.ts +0 -8
  170. package/build/tools/zero-trust-network.d.ts.map +0 -1
@@ -382,7 +382,7 @@ export function registerNetworkDefenseTools(server) {
382
382
  findings.push({ check: sc.key, status: current === sc.expected ? "PASS" : "FAIL", value: current, description: `${sc.desc} (should be ${sc.expected})` });
383
383
  }
384
384
  }
385
- return { content: [createTextContent(JSON.stringify({ summary: { total: findings.length, pass: findings.filter(f => f.status === "PASS").length, fail: findings.filter(f => f.status === "FAIL").length }, ipv6Enabled: !disabled, findings }, null, 2))] };
385
+ return { content: [createTextContent(JSON.stringify({ summary: { total: findings.length, pass: findings.filter(f => f.status === "PASS").length, fail: findings.filter(f => f.status === "FAIL").length }, ipv6Enabled: !disabled, findings }))] };
386
386
  }
387
387
  catch (error) {
388
388
  return { content: [createErrorContent(error instanceof Error ? error.message : String(error))], isError: true };
@@ -557,7 +557,7 @@ export function registerNetworkDefenseTools(server) {
557
557
  if (violations.length > 0) {
558
558
  text += `--- Violations ---\n`;
559
559
  for (const v of violations) {
560
- text += ` ${v}\n`;
560
+ text += ` WARNING: ${v}\n`;
561
561
  }
562
562
  }
563
563
  if (natBypasses.length > 0) {
@@ -692,7 +692,7 @@ export function registerNetworkDefenseTools(server) {
692
692
  if (concerns.length > 0) {
693
693
  text += `--- Security Concerns ---\n`;
694
694
  for (const c of concerns) {
695
- text += ` ${c}\n`;
695
+ text += ` WARNING: ${c}\n`;
696
696
  }
697
697
  }
698
698
  return { content: [createTextContent(text)] };
@@ -183,7 +183,7 @@ export function registerPatchManagementTools(server) {
183
183
  status: packages.length === 0 ? "UP_TO_DATE" : securityPkgs.length > 0 ? "SECURITY_UPDATES_PENDING" : "UPDATES_AVAILABLE",
184
184
  },
185
185
  packages: displayPkgs.slice(0, 100),
186
- }, null, 2))],
186
+ }))],
187
187
  };
188
188
  }
189
189
  catch (error) {
@@ -206,7 +206,7 @@ export function registerPatchManagementTools(server) {
206
206
  supported: false,
207
207
  message: `Automatic updates are not natively supported on ${da.distro.name}.`,
208
208
  recommendation: au.installHint,
209
- }, null, 2))],
209
+ }))],
210
210
  };
211
211
  }
212
212
  const pkgCheckResult = await executeCommand({
@@ -325,8 +325,8 @@ export function registerPatchManagementTools(server) {
325
325
  ? `CRITICAL: Install auto-updates: ${au.installHint}`
326
326
  : failCount > 0
327
327
  ? "WARNING: Automatic security updates not fully configured"
328
- : "PASS: Automatic security updates properly configured",
329
- }, null, 2))],
328
+ : "Automatic security updates properly configured",
329
+ }))],
330
330
  };
331
331
  }
332
332
  catch (error) {
@@ -347,7 +347,7 @@ export function registerPatchManagementTools(server) {
347
347
  distro: da.summary,
348
348
  error: "Package integrity checking not supported on this distribution",
349
349
  recommendation: ic.installHint,
350
- }, null, 2))],
350
+ }))],
351
351
  };
352
352
  }
353
353
  let cmd;
@@ -414,7 +414,7 @@ export function registerPatchManagementTools(server) {
414
414
  note: changed.length > 0
415
415
  ? "Modified files detected. Review if changes are legitimate (config edits) or suspicious (potential compromise)."
416
416
  : "All checked files match their package checksums.",
417
- }, null, 2))],
417
+ }))],
418
418
  };
419
419
  }
420
420
  catch (error) {
@@ -425,7 +425,7 @@ export function registerPatchManagementTools(server) {
425
425
  content: [createTextContent(JSON.stringify({
426
426
  error: `${da?.integrity.toolName ?? "Integrity tool"} not available`,
427
427
  recommendation: da?.integrity.installHint ?? "Install the appropriate integrity checking tool",
428
- }, null, 2))],
428
+ }))],
429
429
  };
430
430
  }
431
431
  return {
@@ -560,7 +560,7 @@ export function registerPatchManagementTools(server) {
560
560
  ...(unmitigated.length > 0 ? [`${unmitigated.length} CPU vulnerabilities not fully mitigated`] : []),
561
561
  ...(installedKernels.length > 3 ? [`Multiple old kernels installed — consider removing unused: ${cleanupHint}`] : []),
562
562
  ],
563
- }, null, 2))],
563
+ }))],
564
564
  };
565
565
  }
566
566
  catch (error) {
@@ -8,7 +8,7 @@
8
8
  * capability abuse, namespace isolation, anomalous behavior, and cgroup resource limits.
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, } from "../core/parsers.js";
13
13
  // ── Constants ──────────────────────────────────────────────────────────────────
14
14
  /** Processes known to legitimately run as root */
@@ -27,53 +27,6 @@ const DANGEROUS_CAPABILITIES = new Set([
27
27
  ]);
28
28
  /** Maximum number of processes to inspect to avoid overwhelming output */
29
29
  const MAX_PROCESSES = 100;
30
- /**
31
- * Run a command via spawnSafe and collect output as a promise.
32
- * Handles errors gracefully — returns error info instead of throwing.
33
- */
34
- async function runCommand(command, args, timeoutMs = 30_000) {
35
- return new Promise((resolve) => {
36
- let child;
37
- try {
38
- child = spawnSafe(command, args);
39
- }
40
- catch (err) {
41
- const msg = err instanceof Error ? err.message : String(err);
42
- resolve({ stdout: "", stderr: msg, exitCode: -1 });
43
- return;
44
- }
45
- let stdout = "";
46
- let stderr = "";
47
- let resolved = false;
48
- const timer = setTimeout(() => {
49
- if (!resolved) {
50
- resolved = true;
51
- child.kill("SIGTERM");
52
- resolve({ stdout, stderr: stderr + "\n[TIMEOUT]", exitCode: -1 });
53
- }
54
- }, timeoutMs);
55
- child.stdout?.on("data", (data) => {
56
- stdout += data.toString();
57
- });
58
- child.stderr?.on("data", (data) => {
59
- stderr += data.toString();
60
- });
61
- child.on("close", (code) => {
62
- if (!resolved) {
63
- resolved = true;
64
- clearTimeout(timer);
65
- resolve({ stdout, stderr, exitCode: code ?? -1 });
66
- }
67
- });
68
- child.on("error", (err) => {
69
- if (!resolved) {
70
- resolved = true;
71
- clearTimeout(timer);
72
- resolve({ stdout, stderr: err.message, exitCode: -1 });
73
- }
74
- });
75
- });
76
- }
77
30
  /**
78
31
  * Parse `ps auxf` output into structured process info.
79
32
  */
@@ -133,12 +86,12 @@ function isUnusualPath(command) {
133
86
  async function auditRunning(pid, filter, showAll) {
134
87
  const sections = [];
135
88
  const findings = [];
136
- sections.push("🔍 Process Security Audit");
137
- sections.push("=".repeat(50));
89
+ sections.push("Process Security Audit");
90
+ sections.push("");
138
91
  // Get process list
139
92
  const psResult = await runCommand("ps", ["auxf"]);
140
93
  if (psResult.exitCode !== 0) {
141
- sections.push(`\n⚠️ Failed to get process list: ${psResult.stderr}`);
94
+ sections.push(`\nWARNING: Failed to get process list: ${psResult.stderr}`);
142
95
  return { sections, findings };
143
96
  }
144
97
  let processes = parsePsOutput(psResult.stdout);
@@ -146,7 +99,7 @@ async function auditRunning(pid, filter, showAll) {
146
99
  if (pid !== undefined) {
147
100
  processes = processes.filter((p) => p.pid === pid);
148
101
  if (processes.length === 0) {
149
- sections.push(`\n⚠️ No process found with PID ${pid}`);
102
+ sections.push(`\nWARNING: No process found with PID ${pid}`);
150
103
  return { sections, findings };
151
104
  }
152
105
  }
@@ -233,7 +186,7 @@ async function auditRunning(pid, filter, showAll) {
233
186
  if (deletedExe.length > 0) {
234
187
  sections.push("\n── Processes with Deleted Executables ──");
235
188
  for (const p of deletedExe) {
236
- sections.push(` PID ${p.pid}: ${p.command}`);
189
+ sections.push(` CRITICAL: PID ${p.pid}: ${p.command}`);
237
190
  findings.push({
238
191
  severity: "CRITICAL",
239
192
  category: "deleted_exe",
@@ -245,7 +198,7 @@ async function auditRunning(pid, filter, showAll) {
245
198
  }
246
199
  // Summary
247
200
  if (!showAll && findings.length === 0) {
248
- sections.push("\n✅ No suspicious processes detected.");
201
+ sections.push("\nNo suspicious processes detected.");
249
202
  }
250
203
  else if (showAll) {
251
204
  sections.push("\n── All Processes ──");
@@ -258,13 +211,13 @@ async function auditRunning(pid, filter, showAll) {
258
211
  async function checkCapabilities(pid, filter) {
259
212
  const sections = [];
260
213
  const findings = [];
261
- sections.push("🔐 Process Capabilities Check");
262
- sections.push("=".repeat(50));
214
+ sections.push("Process Capabilities Check");
215
+ sections.push("");
263
216
  if (pid !== undefined) {
264
217
  // Check specific PID capabilities
265
218
  const capsResult = await runCommand("getpcaps", [String(pid)]);
266
219
  if (capsResult.exitCode !== 0) {
267
- sections.push(`\n⚠️ Failed to get capabilities for PID ${pid}: ${capsResult.stderr}`);
220
+ sections.push(`\nWARNING: Failed to get capabilities for PID ${pid}: ${capsResult.stderr}`);
268
221
  return { sections, findings };
269
222
  }
270
223
  sections.push(`\nCapabilities for PID ${pid}:`);
@@ -286,7 +239,7 @@ async function checkCapabilities(pid, filter) {
286
239
  // Scan processes for elevated capabilities
287
240
  const psResult = await runCommand("ps", ["-eo", "pid"]);
288
241
  if (psResult.exitCode !== 0) {
289
- sections.push("\n⚠️ Failed to list processes");
242
+ sections.push("\nWARNING: Failed to list processes");
290
243
  return { sections, findings };
291
244
  }
292
245
  const pids = psResult.stdout.trim().split("\n")
@@ -340,7 +293,7 @@ async function checkCapabilities(pid, filter) {
340
293
  }
341
294
  }
342
295
  else {
343
- sections.push("\n✅ No processes with elevated capabilities found.");
296
+ sections.push("\nNo processes with elevated capabilities found.");
344
297
  }
345
298
  }
346
299
  return { sections, findings };
@@ -348,13 +301,13 @@ async function checkCapabilities(pid, filter) {
348
301
  async function checkNamespaces(pid, _filter) {
349
302
  const sections = [];
350
303
  const findings = [];
351
- sections.push("📦 Process Namespace Analysis");
352
- sections.push("=".repeat(50));
304
+ sections.push("Process Namespace Analysis");
305
+ sections.push("");
353
306
  if (pid !== undefined) {
354
307
  // Show namespace details for specific PID
355
308
  const nsResult = await runCommand("ls", ["-la", `/proc/${pid}/ns/`]);
356
309
  if (nsResult.exitCode !== 0) {
357
- sections.push(`\n⚠️ Cannot read namespaces for PID ${pid}: ${nsResult.stderr}`);
310
+ sections.push(`\nCannot read namespaces for PID ${pid}: ${nsResult.stderr}`);
358
311
  return { sections, findings };
359
312
  }
360
313
  sections.push(`\nNamespace details for PID ${pid}:`);
@@ -380,7 +333,7 @@ async function checkNamespaces(pid, _filter) {
380
333
  for (const [nsType, nsId] of pidNsMap) {
381
334
  const initId = initNsMap.get(nsType);
382
335
  const inRootNs = initId === nsId;
383
- const icon = inRootNs ? "⚠️" : "";
336
+ const icon = inRootNs ? "WARNING" : "PASS";
384
337
  sections.push(` ${icon} ${nsType}: ${inRootNs ? "in root namespace" : "isolated"} (${nsId})`);
385
338
  if (inRootNs && !["user", "cgroup"].includes(nsType)) {
386
339
  findings.push({
@@ -400,7 +353,7 @@ async function checkNamespaces(pid, _filter) {
400
353
  // Retry with sudo
401
354
  const sudoLsnsResult = await runCommand("sudo", ["lsns"]);
402
355
  if (sudoLsnsResult.exitCode !== 0) {
403
- sections.push("\n⚠️ Cannot list namespaces (lsns not available or permission denied)");
356
+ sections.push("\nCannot list namespaces (lsns not available or permission denied)");
404
357
  return { sections, findings };
405
358
  }
406
359
  sections.push("\n── Active Namespaces ──");
@@ -437,12 +390,12 @@ async function checkNamespaces(pid, _filter) {
437
390
  async function detectAnomalies(pid, filter) {
438
391
  const sections = [];
439
392
  const findings = [];
440
- sections.push("🚨 Process Anomaly Detection");
441
- sections.push("=".repeat(50));
393
+ sections.push("Process Anomaly Detection");
394
+ sections.push("");
442
395
  // Get process list for analysis
443
396
  const psResult = await runCommand("ps", ["-eo", "pid,ppid,user,comm"]);
444
397
  if (psResult.exitCode !== 0) {
445
- sections.push("\n⚠️ Failed to get process list");
398
+ sections.push("\nWARNING: Failed to get process list");
446
399
  return { sections, findings };
447
400
  }
448
401
  const psLines = psResult.stdout.trim().split("\n").slice(1);
@@ -472,7 +425,7 @@ async function detectAnomalies(pid, filter) {
472
425
  const exeResult = await runCommand("ls", ["-la", `/proc/${proc.pid}/exe`]);
473
426
  if (exeResult.exitCode === 0 && exeResult.stdout.includes("(deleted)")) {
474
427
  deletedCount++;
475
- sections.push(` PID ${proc.pid} (${proc.comm}): executable deleted`);
428
+ sections.push(` CRITICAL: PID ${proc.pid} (${proc.comm}): executable deleted`);
476
429
  findings.push({
477
430
  severity: "CRITICAL",
478
431
  category: "deleted_binary",
@@ -483,7 +436,7 @@ async function detectAnomalies(pid, filter) {
483
436
  }
484
437
  }
485
438
  if (deletedCount === 0)
486
- sections.push(" No processes with deleted binaries");
439
+ sections.push(" No processes with deleted binaries");
487
440
  // 2. Cross-reference network connections with expected services
488
441
  sections.push("\n── Unexpected Network Connections ──");
489
442
  const ssResult = await runCommand("ss", ["-tlnp"]);
@@ -493,11 +446,11 @@ async function detectAnomalies(pid, filter) {
493
446
  sections.push(` ${line.trim()}`);
494
447
  }
495
448
  if (ssLines.length === 0) {
496
- sections.push(" No listening TCP connections");
449
+ sections.push(" No listening TCP connections");
497
450
  }
498
451
  }
499
452
  else {
500
- sections.push(" ⚠️ Could not check network connections");
453
+ sections.push(" Could not check network connections");
501
454
  }
502
455
  // 3. Check for shell spawning from non-shell parents
503
456
  sections.push("\n── Shell Spawning Analysis ──");
@@ -511,7 +464,7 @@ async function detectAnomalies(pid, filter) {
511
464
  parent.comm !== "screen" && parent.comm !== "tmux" && parent.comm !== "script" &&
512
465
  parent.comm !== "getty" && parent.comm !== "agetty" && parent.comm !== "systemd") {
513
466
  suspiciousShellCount++;
514
- sections.push(` ⚠️ PID ${shell.pid} (${shell.comm}) spawned by ${parent.comm} (PID ${parent.pid})`);
467
+ sections.push(` WARNING: PID ${shell.pid} (${shell.comm}) spawned by ${parent.comm} (PID ${parent.pid})`);
515
468
  findings.push({
516
469
  severity: "HIGH",
517
470
  category: "suspicious_shell",
@@ -522,7 +475,7 @@ async function detectAnomalies(pid, filter) {
522
475
  }
523
476
  }
524
477
  if (suspiciousShellCount === 0)
525
- sections.push(" No suspicious shell spawning detected");
478
+ sections.push(" No suspicious shell spawning detected");
526
479
  // 4. Check for open file descriptors to sensitive files
527
480
  sections.push("\n── Sensitive File Access ──");
528
481
  const sensitiveFiles = ["/etc/shadow", "/etc/passwd", ".ssh/id_rsa", ".ssh/id_ed25519", "private.key"];
@@ -535,7 +488,7 @@ async function detectAnomalies(pid, filter) {
535
488
  for (const sf of sensitiveFiles) {
536
489
  if (fdResult.stdout.includes(sf)) {
537
490
  sensitiveAccessCount++;
538
- sections.push(` ⚠️ PID ${proc.pid} (${proc.comm}) has open fd to ${sf}`);
491
+ sections.push(` WARNING: PID ${proc.pid} (${proc.comm}) has open fd to ${sf}`);
539
492
  findings.push({
540
493
  severity: "HIGH",
541
494
  category: "sensitive_file_access",
@@ -547,7 +500,7 @@ async function detectAnomalies(pid, filter) {
547
500
  }
548
501
  }
549
502
  if (sensitiveAccessCount === 0)
550
- sections.push(" No suspicious sensitive file access");
503
+ sections.push(" No suspicious sensitive file access");
551
504
  // 5. Check for suspicious environment variables
552
505
  sections.push("\n── Suspicious Environment Variables ──");
553
506
  let suspiciousEnvCount = 0;
@@ -561,7 +514,7 @@ async function detectAnomalies(pid, filter) {
561
514
  envStr.includes("nc -e") || envStr.includes("mkfifo") ||
562
515
  envStr.includes("PAYLOAD") || envStr.includes("SHELLCODE")) {
563
516
  suspiciousEnvCount++;
564
- sections.push(` PID ${proc.pid} (${proc.comm}): suspicious environment variables detected`);
517
+ sections.push(` CRITICAL: PID ${proc.pid} (${proc.comm}): suspicious environment variables detected`);
565
518
  findings.push({
566
519
  severity: "CRITICAL",
567
520
  category: "suspicious_env",
@@ -572,19 +525,19 @@ async function detectAnomalies(pid, filter) {
572
525
  }
573
526
  }
574
527
  if (suspiciousEnvCount === 0)
575
- sections.push(" No suspicious environment variables detected");
528
+ sections.push(" No suspicious environment variables detected");
576
529
  return { sections, findings };
577
530
  }
578
531
  async function cgroupAudit(pid, _filter) {
579
532
  const sections = [];
580
533
  const findings = [];
581
- sections.push("📊 Cgroup Resource Audit");
582
- sections.push("=".repeat(50));
534
+ sections.push("Cgroup Resource Audit");
535
+ sections.push("");
583
536
  if (pid !== undefined) {
584
537
  // Inspect specific process cgroup membership
585
538
  const cgroupResult = await runCommand("cat", [`/proc/${pid}/cgroup`]);
586
539
  if (cgroupResult.exitCode !== 0) {
587
- sections.push(`\n⚠️ Cannot read cgroup for PID ${pid}: ${cgroupResult.stderr}`);
540
+ sections.push(`\nCannot read cgroup for PID ${pid}: ${cgroupResult.stderr}`);
588
541
  return { sections, findings };
589
542
  }
590
543
  sections.push(`\nCgroup membership for PID ${pid}:`);
@@ -600,7 +553,7 @@ async function cgroupAudit(pid, _filter) {
600
553
  const memMaxResult = await runCommand("cat", [`/sys/fs/cgroup${cgroupPath}/memory.max`]);
601
554
  if (memMaxResult.exitCode === 0) {
602
555
  const memMax = memMaxResult.stdout.trim();
603
- sections.push(` Memory limit: ${memMax === "max" ? "unlimited ⚠️" : memMax}`);
556
+ sections.push(` Memory limit: ${memMax === "max" ? "unlimited WARNING" : memMax}`);
604
557
  if (memMax === "max") {
605
558
  findings.push({
606
559
  severity: "LOW",
@@ -613,7 +566,7 @@ async function cgroupAudit(pid, _filter) {
613
566
  const cpuMaxResult = await runCommand("cat", [`/sys/fs/cgroup${cgroupPath}/cpu.max`]);
614
567
  if (cpuMaxResult.exitCode === 0) {
615
568
  const cpuMax = cpuMaxResult.stdout.trim();
616
- sections.push(` CPU limit: ${cpuMax === "max 100000" ? "unlimited ⚠️" : cpuMax}`);
569
+ sections.push(` CPU limit: ${cpuMax === "max 100000" ? "unlimited WARNING" : cpuMax}`);
617
570
  if (cpuMax.startsWith("max")) {
618
571
  findings.push({
619
572
  severity: "LOW",
@@ -669,7 +622,7 @@ async function cgroupAudit(pid, _filter) {
669
622
  // ── Format helpers ─────────────────────────────────────────────────────────────
670
623
  function formatFindings(findings) {
671
624
  if (findings.length === 0)
672
- return "\n✅ No security findings.";
625
+ return "\nNo security findings.";
673
626
  const lines = ["\n── Security Findings Summary ──"];
674
627
  const bySeverity = {};
675
628
  for (const f of findings) {
@@ -678,18 +631,11 @@ function formatFindings(findings) {
678
631
  bySeverity[f.severity].push(f);
679
632
  }
680
633
  const severityOrder = ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"];
681
- const icons = {
682
- CRITICAL: "⛔",
683
- HIGH: "🔴",
684
- MEDIUM: "🟠",
685
- LOW: "🟡",
686
- INFO: "ℹ️",
687
- };
688
634
  for (const sev of severityOrder) {
689
635
  const items = bySeverity[sev];
690
636
  if (!items || items.length === 0)
691
637
  continue;
692
- lines.push(`\n ${icons[sev]} ${sev} (${items.length}):`);
638
+ lines.push(`\n ${sev} (${items.length}):`);
693
639
  for (const f of items) {
694
640
  const pidStr = f.pid ? ` [PID ${f.pid}]` : "";
695
641
  lines.push(` - ${f.message}${pidStr}`);
@@ -710,7 +656,7 @@ function formatAsJson(action, findings, rawSections) {
710
656
  process: f.process || null,
711
657
  })),
712
658
  rawOutput: rawSections.join("\n"),
713
- }, null, 2);
659
+ });
714
660
  }
715
661
  // ── Registration entry point ───────────────────────────────────────────────
716
662
  export function registerProcessSecurityTools(server) {