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.
- package/CHANGELOG.md +471 -0
- package/LICENSE +21 -0
- package/README.md +242 -0
- package/build/core/auto-installer.d.ts +102 -0
- package/build/core/auto-installer.d.ts.map +1 -0
- package/build/core/auto-installer.js +833 -0
- package/build/core/backup-manager.d.ts +63 -0
- package/build/core/backup-manager.d.ts.map +1 -0
- package/build/core/backup-manager.js +189 -0
- package/build/core/changelog.d.ts +75 -0
- package/build/core/changelog.d.ts.map +1 -0
- package/build/core/changelog.js +123 -0
- package/build/core/command-allowlist.d.ts +129 -0
- package/build/core/command-allowlist.d.ts.map +1 -0
- package/build/core/command-allowlist.js +849 -0
- package/build/core/config.d.ts +79 -0
- package/build/core/config.d.ts.map +1 -0
- package/build/core/config.js +193 -0
- package/build/core/dependency-validator.d.ts +106 -0
- package/build/core/dependency-validator.d.ts.map +1 -0
- package/build/core/dependency-validator.js +405 -0
- package/build/core/distro-adapter.d.ts +177 -0
- package/build/core/distro-adapter.d.ts.map +1 -0
- package/build/core/distro-adapter.js +481 -0
- package/build/core/distro.d.ts +68 -0
- package/build/core/distro.d.ts.map +1 -0
- package/build/core/distro.js +457 -0
- package/build/core/encrypted-state.d.ts +76 -0
- package/build/core/encrypted-state.d.ts.map +1 -0
- package/build/core/encrypted-state.js +209 -0
- package/build/core/executor.d.ts +56 -0
- package/build/core/executor.d.ts.map +1 -0
- package/build/core/executor.js +350 -0
- package/build/core/installer.d.ts +92 -0
- package/build/core/installer.d.ts.map +1 -0
- package/build/core/installer.js +1072 -0
- package/build/core/logger.d.ts +102 -0
- package/build/core/logger.d.ts.map +1 -0
- package/build/core/logger.js +132 -0
- package/build/core/parsers.d.ts +151 -0
- package/build/core/parsers.d.ts.map +1 -0
- package/build/core/parsers.js +479 -0
- package/build/core/policy-engine.d.ts +170 -0
- package/build/core/policy-engine.d.ts.map +1 -0
- package/build/core/policy-engine.js +656 -0
- package/build/core/preflight.d.ts +157 -0
- package/build/core/preflight.d.ts.map +1 -0
- package/build/core/preflight.js +638 -0
- package/build/core/privilege-manager.d.ts +108 -0
- package/build/core/privilege-manager.d.ts.map +1 -0
- package/build/core/privilege-manager.js +363 -0
- package/build/core/rate-limiter.d.ts +67 -0
- package/build/core/rate-limiter.d.ts.map +1 -0
- package/build/core/rate-limiter.js +129 -0
- package/build/core/rollback.d.ts +73 -0
- package/build/core/rollback.d.ts.map +1 -0
- package/build/core/rollback.js +278 -0
- package/build/core/safeguards.d.ts +58 -0
- package/build/core/safeguards.d.ts.map +1 -0
- package/build/core/safeguards.js +448 -0
- package/build/core/sanitizer.d.ts +118 -0
- package/build/core/sanitizer.d.ts.map +1 -0
- package/build/core/sanitizer.js +459 -0
- package/build/core/secure-fs.d.ts +67 -0
- package/build/core/secure-fs.d.ts.map +1 -0
- package/build/core/secure-fs.js +143 -0
- package/build/core/spawn-safe.d.ts +55 -0
- package/build/core/spawn-safe.d.ts.map +1 -0
- package/build/core/spawn-safe.js +146 -0
- package/build/core/sudo-guard.d.ts +145 -0
- package/build/core/sudo-guard.d.ts.map +1 -0
- package/build/core/sudo-guard.js +349 -0
- package/build/core/sudo-session.d.ts +100 -0
- package/build/core/sudo-session.d.ts.map +1 -0
- package/build/core/sudo-session.js +319 -0
- package/build/core/tool-dependencies.d.ts +61 -0
- package/build/core/tool-dependencies.d.ts.map +1 -0
- package/build/core/tool-dependencies.js +571 -0
- package/build/core/tool-registry.d.ts +111 -0
- package/build/core/tool-registry.d.ts.map +1 -0
- package/build/core/tool-registry.js +656 -0
- package/build/core/tool-wrapper.d.ts +73 -0
- package/build/core/tool-wrapper.d.ts.map +1 -0
- package/build/core/tool-wrapper.js +296 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +247 -0
- package/build/tools/access-control.d.ts +9 -0
- package/build/tools/access-control.d.ts.map +1 -0
- package/build/tools/access-control.js +1818 -0
- package/build/tools/api-security.d.ts +12 -0
- package/build/tools/api-security.d.ts.map +1 -0
- package/build/tools/api-security.js +901 -0
- package/build/tools/app-hardening.d.ts +11 -0
- package/build/tools/app-hardening.d.ts.map +1 -0
- package/build/tools/app-hardening.js +768 -0
- package/build/tools/backup.d.ts +8 -0
- package/build/tools/backup.d.ts.map +1 -0
- package/build/tools/backup.js +381 -0
- package/build/tools/cloud-security.d.ts +17 -0
- package/build/tools/cloud-security.d.ts.map +1 -0
- package/build/tools/cloud-security.js +739 -0
- package/build/tools/compliance.d.ts +10 -0
- package/build/tools/compliance.d.ts.map +1 -0
- package/build/tools/compliance.js +1225 -0
- package/build/tools/container-security.d.ts +14 -0
- package/build/tools/container-security.d.ts.map +1 -0
- package/build/tools/container-security.js +788 -0
- package/build/tools/deception.d.ts +13 -0
- package/build/tools/deception.d.ts.map +1 -0
- package/build/tools/deception.js +763 -0
- package/build/tools/dns-security.d.ts +93 -0
- package/build/tools/dns-security.d.ts.map +1 -0
- package/build/tools/dns-security.js +745 -0
- package/build/tools/drift-detection.d.ts +8 -0
- package/build/tools/drift-detection.d.ts.map +1 -0
- package/build/tools/drift-detection.js +326 -0
- package/build/tools/ebpf-security.d.ts +15 -0
- package/build/tools/ebpf-security.d.ts.map +1 -0
- package/build/tools/ebpf-security.js +294 -0
- package/build/tools/encryption.d.ts +9 -0
- package/build/tools/encryption.d.ts.map +1 -0
- package/build/tools/encryption.js +1667 -0
- package/build/tools/firewall.d.ts +9 -0
- package/build/tools/firewall.d.ts.map +1 -0
- package/build/tools/firewall.js +1398 -0
- package/build/tools/hardening.d.ts +10 -0
- package/build/tools/hardening.d.ts.map +1 -0
- package/build/tools/hardening.js +2654 -0
- package/build/tools/ids.d.ts +9 -0
- package/build/tools/ids.d.ts.map +1 -0
- package/build/tools/ids.js +624 -0
- package/build/tools/incident-response.d.ts +10 -0
- package/build/tools/incident-response.d.ts.map +1 -0
- package/build/tools/incident-response.js +1180 -0
- package/build/tools/logging.d.ts +12 -0
- package/build/tools/logging.d.ts.map +1 -0
- package/build/tools/logging.js +454 -0
- package/build/tools/malware.d.ts +10 -0
- package/build/tools/malware.d.ts.map +1 -0
- package/build/tools/malware.js +532 -0
- package/build/tools/meta.d.ts +11 -0
- package/build/tools/meta.d.ts.map +1 -0
- package/build/tools/meta.js +2278 -0
- package/build/tools/network-defense.d.ts +12 -0
- package/build/tools/network-defense.d.ts.map +1 -0
- package/build/tools/network-defense.js +760 -0
- package/build/tools/patch-management.d.ts +3 -0
- package/build/tools/patch-management.d.ts.map +1 -0
- package/build/tools/patch-management.js +708 -0
- package/build/tools/process-security.d.ts +12 -0
- package/build/tools/process-security.d.ts.map +1 -0
- package/build/tools/process-security.js +784 -0
- package/build/tools/reporting.d.ts +11 -0
- package/build/tools/reporting.d.ts.map +1 -0
- package/build/tools/reporting.js +559 -0
- package/build/tools/secrets.d.ts +9 -0
- package/build/tools/secrets.d.ts.map +1 -0
- package/build/tools/secrets.js +596 -0
- package/build/tools/siem-integration.d.ts +18 -0
- package/build/tools/siem-integration.d.ts.map +1 -0
- package/build/tools/siem-integration.js +754 -0
- package/build/tools/sudo-management.d.ts +18 -0
- package/build/tools/sudo-management.d.ts.map +1 -0
- package/build/tools/sudo-management.js +737 -0
- package/build/tools/supply-chain-security.d.ts +8 -0
- package/build/tools/supply-chain-security.d.ts.map +1 -0
- package/build/tools/supply-chain-security.js +256 -0
- package/build/tools/threat-intel.d.ts +22 -0
- package/build/tools/threat-intel.d.ts.map +1 -0
- package/build/tools/threat-intel.js +749 -0
- package/build/tools/vulnerability-management.d.ts +11 -0
- package/build/tools/vulnerability-management.d.ts.map +1 -0
- package/build/tools/vulnerability-management.js +667 -0
- package/build/tools/waf.d.ts +12 -0
- package/build/tools/waf.d.ts.map +1 -0
- package/build/tools/waf.js +843 -0
- package/build/tools/wireless-security.d.ts +19 -0
- package/build/tools/wireless-security.d.ts.map +1 -0
- package/build/tools/wireless-security.js +826 -0
- package/build/tools/zero-trust-network.d.ts +8 -0
- package/build/tools/zero-trust-network.d.ts.map +1 -0
- package/build/tools/zero-trust-network.js +367 -0
- package/docs/SAFEGUARDS.md +518 -0
- package/docs/TOOLS-REFERENCE.md +665 -0
- package/package.json +87 -0
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Tool Registry — single source of truth for all MCP tool requirements.
|
|
3
|
+
*
|
|
4
|
+
* Replaces and extends `tool-dependencies.ts` with richer dependency metadata
|
|
5
|
+
* including privilege requirements, Python/npm packages, system libraries,
|
|
6
|
+
* required files, and Linux capabilities.
|
|
7
|
+
*
|
|
8
|
+
* v0.5.0: Tool consolidation (157 → 78 tools), each entry represents a
|
|
9
|
+
* consolidated action-based tool.
|
|
10
|
+
* v0.6.0: Extended to 94 tools across 32 modules with 16 new security tools.
|
|
11
|
+
*
|
|
12
|
+
* @module tool-registry
|
|
13
|
+
*/
|
|
14
|
+
import { TOOL_DEPENDENCIES } from "./tool-dependencies.js";
|
|
15
|
+
// ── Registry Class ───────────────────────────────────────────────────────────
|
|
16
|
+
// SECURITY (CORE-021): Module-scoped singleton variable prevents external
|
|
17
|
+
// mutation via (ToolRegistry as any)._instance — inaccessible outside module.
|
|
18
|
+
let _registryInstance = null;
|
|
19
|
+
/**
|
|
20
|
+
* Map-based registry with O(1) lookup for tool manifests.
|
|
21
|
+
* Singleton pattern — use {@link ToolRegistry.instance} to obtain.
|
|
22
|
+
*/
|
|
23
|
+
export class ToolRegistry {
|
|
24
|
+
manifests = new Map();
|
|
25
|
+
/** Get or create the singleton registry instance. */
|
|
26
|
+
static instance() {
|
|
27
|
+
if (!_registryInstance) {
|
|
28
|
+
_registryInstance = new ToolRegistry();
|
|
29
|
+
}
|
|
30
|
+
return _registryInstance;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Reset the singleton (primarily for testing).
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
static resetInstance() {
|
|
37
|
+
_registryInstance = null;
|
|
38
|
+
}
|
|
39
|
+
/** Register a single tool manifest. Overwrites if already registered. */
|
|
40
|
+
register(manifest) {
|
|
41
|
+
this.manifests.set(manifest.toolName, manifest);
|
|
42
|
+
}
|
|
43
|
+
/** Bulk register an array of tool manifests. */
|
|
44
|
+
registerAll(manifests) {
|
|
45
|
+
for (const m of manifests) {
|
|
46
|
+
this.register(m);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Get manifest for a tool, or `undefined` if unregistered. */
|
|
50
|
+
getManifest(toolName) {
|
|
51
|
+
return this.manifests.get(toolName);
|
|
52
|
+
}
|
|
53
|
+
/** Get all tool names that list `binary` in their `requiredBinaries`. */
|
|
54
|
+
getToolsRequiring(binary) {
|
|
55
|
+
const result = [];
|
|
56
|
+
for (const m of this.manifests.values()) {
|
|
57
|
+
if (m.requiredBinaries.includes(binary)) {
|
|
58
|
+
result.push(m.toolName);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
/** Get all manifests whose `category` matches. */
|
|
64
|
+
getToolsByCategory(category) {
|
|
65
|
+
const result = [];
|
|
66
|
+
for (const m of this.manifests.values()) {
|
|
67
|
+
if (m.category === category) {
|
|
68
|
+
result.push(m);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
/** Collect every unique required binary across all registered tools. */
|
|
74
|
+
getAllRequiredBinaries() {
|
|
75
|
+
const bins = new Set();
|
|
76
|
+
for (const m of this.manifests.values()) {
|
|
77
|
+
for (const b of m.requiredBinaries) {
|
|
78
|
+
bins.add(b);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return bins;
|
|
82
|
+
}
|
|
83
|
+
/** Get all manifests that require sudo (`always` or `conditional`). */
|
|
84
|
+
getToolsNeedingSudo() {
|
|
85
|
+
const result = [];
|
|
86
|
+
for (const m of this.manifests.values()) {
|
|
87
|
+
if (m.sudo === "always" || m.sudo === "conditional") {
|
|
88
|
+
result.push(m);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/** Check whether a tool name is registered. */
|
|
94
|
+
has(toolName) {
|
|
95
|
+
return this.manifests.has(toolName);
|
|
96
|
+
}
|
|
97
|
+
/** Return every registered manifest as an array. */
|
|
98
|
+
getAll() {
|
|
99
|
+
return Array.from(this.manifests.values());
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// ── Category Inference ───────────────────────────────────────────────────────
|
|
103
|
+
/** Prefix → category mapping used by {@link inferCategory}. */
|
|
104
|
+
const CATEGORY_PREFIX_MAP = [
|
|
105
|
+
// Exact-match entries (longer/more specific — checked first)
|
|
106
|
+
["supply_chain", "supply-chain"],
|
|
107
|
+
["drift_baseline", "drift-detection"],
|
|
108
|
+
["zero_trust", "zero-trust"],
|
|
109
|
+
["incident_response", "incident-response"],
|
|
110
|
+
["app_harden", "app-hardening"],
|
|
111
|
+
["backup", "backup"],
|
|
112
|
+
// Prefix entries (disjoint prefixes)
|
|
113
|
+
["firewall_", "firewall"],
|
|
114
|
+
["harden_", "hardening"],
|
|
115
|
+
["ids_", "ids"],
|
|
116
|
+
["log_", "logging"],
|
|
117
|
+
["netdef_", "network"],
|
|
118
|
+
["compliance_", "compliance"],
|
|
119
|
+
["malware_", "malware"],
|
|
120
|
+
["access_", "access"],
|
|
121
|
+
["crypto_", "encryption"],
|
|
122
|
+
["container_", "container"],
|
|
123
|
+
["patch_", "patch-management"],
|
|
124
|
+
["secrets_", "secrets"],
|
|
125
|
+
["defense_", "meta"],
|
|
126
|
+
["ebpf_", "ebpf"],
|
|
127
|
+
["sudo_", "sudo"],
|
|
128
|
+
["preflight_", "sudo"],
|
|
129
|
+
];
|
|
130
|
+
/**
|
|
131
|
+
* Infer a human-readable category from the MCP tool name.
|
|
132
|
+
*/
|
|
133
|
+
function inferCategory(toolName) {
|
|
134
|
+
for (const [prefix, category] of CATEGORY_PREFIX_MAP) {
|
|
135
|
+
if (toolName === prefix || toolName.startsWith(prefix)) {
|
|
136
|
+
return category;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return "unknown";
|
|
140
|
+
}
|
|
141
|
+
// ── Legacy Migration ─────────────────────────────────────────────────────────
|
|
142
|
+
/**
|
|
143
|
+
* Convert every entry in the legacy `TOOL_DEPENDENCIES` array into a
|
|
144
|
+
* {@link ToolManifest} and register it. Default `sudo` is `'never'`
|
|
145
|
+
* (overridden later by {@link DEFAULT_MANIFESTS}).
|
|
146
|
+
*/
|
|
147
|
+
export function migrateFromLegacy(registry) {
|
|
148
|
+
for (const legacy of TOOL_DEPENDENCIES) {
|
|
149
|
+
const manifest = {
|
|
150
|
+
toolName: legacy.toolName,
|
|
151
|
+
requiredBinaries: [...legacy.requiredBinaries],
|
|
152
|
+
optionalBinaries: legacy.optionalBinaries
|
|
153
|
+
? [...legacy.optionalBinaries]
|
|
154
|
+
: undefined,
|
|
155
|
+
sudo: "never",
|
|
156
|
+
critical: legacy.critical,
|
|
157
|
+
category: inferCategory(legacy.toolName),
|
|
158
|
+
};
|
|
159
|
+
registry.register(manifest);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Static sudo requirement data for all 78 consolidated tools.
|
|
164
|
+
* Each consolidated tool uses action parameters, so sudo is typically
|
|
165
|
+
* "conditional" (depends on which action is selected).
|
|
166
|
+
*/
|
|
167
|
+
const SUDO_OVERLAYS = [
|
|
168
|
+
// ── Firewall tools ────────────────────────────────────────────────────
|
|
169
|
+
{
|
|
170
|
+
toolName: "firewall_iptables",
|
|
171
|
+
sudo: "conditional",
|
|
172
|
+
sudoReason: "Read actions may work without sudo; write actions require root to modify netfilter tables",
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
toolName: "firewall_ufw",
|
|
176
|
+
sudo: "conditional",
|
|
177
|
+
sudoReason: "Status may work without sudo; add/delete rules require root",
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
toolName: "firewall_persist",
|
|
181
|
+
sudo: "always",
|
|
182
|
+
sudoReason: "Saving/restoring firewall rules requires root",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
toolName: "firewall_nftables_list",
|
|
186
|
+
sudo: "always",
|
|
187
|
+
sudoReason: "nftables requires root to list ruleset",
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
toolName: "firewall_policy_audit",
|
|
191
|
+
sudo: "conditional",
|
|
192
|
+
sudoReason: "May work without sudo but shows limited results",
|
|
193
|
+
},
|
|
194
|
+
// ── Hardening tools ───────────────────────────────────────────────────
|
|
195
|
+
{
|
|
196
|
+
toolName: "harden_sysctl",
|
|
197
|
+
sudo: "conditional",
|
|
198
|
+
sudoReason: "get/audit actions may work without sudo; set action requires root",
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
toolName: "harden_service",
|
|
202
|
+
sudo: "conditional",
|
|
203
|
+
sudoReason: "audit/status may work without sudo; manage actions require root",
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
toolName: "harden_permissions",
|
|
207
|
+
sudo: "conditional",
|
|
208
|
+
sudoReason: "check/audit actions may work without sudo; fix action requires root",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
toolName: "harden_systemd",
|
|
212
|
+
sudo: "conditional",
|
|
213
|
+
sudoReason: "audit may work without sudo; apply action requires root for unit overrides",
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
toolName: "harden_kernel",
|
|
217
|
+
sudo: "conditional",
|
|
218
|
+
sudoReason: "audit action may work without sudo; modules/coredump actions may require root",
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
toolName: "harden_bootloader",
|
|
222
|
+
sudo: "conditional",
|
|
223
|
+
sudoReason: "audit may work without sudo; configure action requires root",
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
toolName: "harden_misc",
|
|
227
|
+
sudo: "conditional",
|
|
228
|
+
sudoReason: "audit actions may work without sudo; set actions require root",
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
toolName: "harden_memory",
|
|
232
|
+
sudo: "conditional",
|
|
233
|
+
sudoReason: "audit/report actions work without sudo; enforce_aslr requires root",
|
|
234
|
+
},
|
|
235
|
+
// ── IDS tools ─────────────────────────────────────────────────────────
|
|
236
|
+
{
|
|
237
|
+
toolName: "ids_aide_manage",
|
|
238
|
+
sudo: "always",
|
|
239
|
+
sudoReason: "AIDE database operations require root",
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
toolName: "ids_rootkit_scan",
|
|
243
|
+
sudo: "always",
|
|
244
|
+
sudoReason: "Rootkit scanning requires root (delegates to rkhunter/chkrootkit)",
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
toolName: "ids_file_integrity_check",
|
|
248
|
+
sudo: "conditional",
|
|
249
|
+
sudoReason: "Baseline creation may use sudo tee; display/compare modes do not",
|
|
250
|
+
},
|
|
251
|
+
// ── Logging tools ─────────────────────────────────────────────────────
|
|
252
|
+
{
|
|
253
|
+
toolName: "log_auditd",
|
|
254
|
+
sudo: "always",
|
|
255
|
+
sudoReason: "Auditd requires root for rule management and log searching",
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
toolName: "log_journalctl_query",
|
|
259
|
+
sudo: "conditional",
|
|
260
|
+
sudoReason: "May work without sudo but shows limited results",
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
toolName: "log_fail2ban",
|
|
264
|
+
sudo: "conditional",
|
|
265
|
+
sudoReason: "status may work without sudo; ban/unban/reload actions require root",
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
toolName: "log_system",
|
|
269
|
+
sudo: "conditional",
|
|
270
|
+
sudoReason: "May need sudo to read restricted log files",
|
|
271
|
+
},
|
|
272
|
+
// ── Network defense tools ─────────────────────────────────────────────
|
|
273
|
+
{
|
|
274
|
+
toolName: "netdef_connections",
|
|
275
|
+
sudo: "conditional",
|
|
276
|
+
sudoReason: "May work without sudo but shows limited results",
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
toolName: "netdef_capture",
|
|
280
|
+
sudo: "always",
|
|
281
|
+
sudoReason: "Packet capture requires root",
|
|
282
|
+
capabilities: ["CAP_NET_RAW"],
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
toolName: "netdef_security_audit",
|
|
286
|
+
sudo: "conditional",
|
|
287
|
+
sudoReason: "scan_detect may need log access; self_scan requires root for SYN scans",
|
|
288
|
+
},
|
|
289
|
+
// ── Compliance tools ──────────────────────────────────────────────────
|
|
290
|
+
{
|
|
291
|
+
toolName: "compliance_lynis_audit",
|
|
292
|
+
sudo: "always",
|
|
293
|
+
sudoReason: "Lynis requires root for comprehensive audit",
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
toolName: "compliance_oscap_scan",
|
|
297
|
+
sudo: "always",
|
|
298
|
+
sudoReason: "OpenSCAP requires root for system scanning",
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
toolName: "compliance_check",
|
|
302
|
+
sudo: "conditional",
|
|
303
|
+
sudoReason: "CIS checks may need root for full results; framework checks vary",
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
toolName: "compliance_policy_evaluate",
|
|
307
|
+
sudo: "never",
|
|
308
|
+
sudoReason: "Reads files and evaluates policy without privileged operations",
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
toolName: "compliance_report",
|
|
312
|
+
sudo: "conditional",
|
|
313
|
+
sudoReason: "May invoke Lynis which requires root for comprehensive audit",
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
toolName: "compliance_cron_restrict",
|
|
317
|
+
sudo: "always",
|
|
318
|
+
sudoReason: "Cron access restriction requires root",
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
toolName: "compliance_tmp_hardening",
|
|
322
|
+
sudo: "always",
|
|
323
|
+
sudoReason: "Mount operations require root",
|
|
324
|
+
},
|
|
325
|
+
// ── Malware tools ─────────────────────────────────────────────────────
|
|
326
|
+
{
|
|
327
|
+
toolName: "malware_clamav",
|
|
328
|
+
sudo: "conditional",
|
|
329
|
+
sudoReason: "scan may need root for restricted dirs; update always requires root",
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
toolName: "malware_yara_scan",
|
|
333
|
+
sudo: "never",
|
|
334
|
+
sudoReason: "YARA scanning runs as current user",
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
toolName: "malware_file_scan",
|
|
338
|
+
sudo: "conditional",
|
|
339
|
+
sudoReason: "suspicious file scan may need root; webshell detection may need root for web dirs",
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
toolName: "malware_quarantine_manage",
|
|
343
|
+
sudo: "never",
|
|
344
|
+
sudoReason: "Manages quarantine files without requiring root",
|
|
345
|
+
},
|
|
346
|
+
// ── Backup tools ──────────────────────────────────────────────────────
|
|
347
|
+
{
|
|
348
|
+
toolName: "backup",
|
|
349
|
+
sudo: "conditional",
|
|
350
|
+
sudoReason: "config/restore/verify/list work without sudo; state snapshot may need sudo for firewall/service data",
|
|
351
|
+
},
|
|
352
|
+
// ── Access control tools ──────────────────────────────────────────────
|
|
353
|
+
{
|
|
354
|
+
toolName: "access_ssh",
|
|
355
|
+
sudo: "conditional",
|
|
356
|
+
sudoReason: "audit/cipher_audit may work without sudo; harden action requires root",
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
toolName: "access_sudo_audit",
|
|
360
|
+
sudo: "conditional",
|
|
361
|
+
sudoReason: "May work without sudo but shows limited results",
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
toolName: "access_user_audit",
|
|
365
|
+
sudo: "conditional",
|
|
366
|
+
sudoReason: "May work without sudo but shows limited results",
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
toolName: "access_password_policy",
|
|
370
|
+
sudo: "conditional",
|
|
371
|
+
sudoReason: "audit may work without sudo; set action requires root",
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
toolName: "access_pam",
|
|
375
|
+
sudo: "conditional",
|
|
376
|
+
sudoReason: "audit needs root to read PAM files; configure requires root",
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
toolName: "access_restrict_shell",
|
|
380
|
+
sudo: "always",
|
|
381
|
+
sudoReason: "Changing user shells requires root",
|
|
382
|
+
},
|
|
383
|
+
// ── Encryption tools ──────────────────────────────────────────────────
|
|
384
|
+
{
|
|
385
|
+
toolName: "crypto_tls",
|
|
386
|
+
sudo: "conditional",
|
|
387
|
+
sudoReason: "remote_audit/cert_expiry work without sudo; config_audit may need root for web server configs",
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
toolName: "crypto_gpg_keys",
|
|
391
|
+
sudo: "never",
|
|
392
|
+
sudoReason: "GPG key operations run as current user",
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
toolName: "crypto_luks_manage",
|
|
396
|
+
sudo: "always",
|
|
397
|
+
sudoReason: "LUKS operations require root",
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
toolName: "crypto_file_hash",
|
|
401
|
+
sudo: "never",
|
|
402
|
+
sudoReason: "Hash computation does not require root",
|
|
403
|
+
},
|
|
404
|
+
// ── Container tools ───────────────────────────────────────────────────
|
|
405
|
+
{
|
|
406
|
+
toolName: "container_docker",
|
|
407
|
+
sudo: "conditional",
|
|
408
|
+
sudoReason: "Docker commands may require root or docker group membership",
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
toolName: "container_apparmor",
|
|
412
|
+
sudo: "conditional",
|
|
413
|
+
sudoReason: "status/list may work without sudo; enforce/complain/install require root",
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
toolName: "container_selinux_manage",
|
|
417
|
+
sudo: "always",
|
|
418
|
+
sudoReason: "SELinux management requires root",
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
toolName: "container_namespace_check",
|
|
422
|
+
sudo: "conditional",
|
|
423
|
+
sudoReason: "May fall back to sudo lsns if unprivileged access insufficient",
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
toolName: "container_image_scan",
|
|
427
|
+
sudo: "never",
|
|
428
|
+
sudoReason: "Trivy/Grype image scanning does not require root",
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
toolName: "container_security_config",
|
|
432
|
+
sudo: "conditional",
|
|
433
|
+
sudoReason: "seccomp_profile generation does not need root; rootless setup may need root for subuid/subgid",
|
|
434
|
+
},
|
|
435
|
+
// ── Patch management tools ────────────────────────────────────────────
|
|
436
|
+
{
|
|
437
|
+
toolName: "patch_update_audit",
|
|
438
|
+
sudo: "always",
|
|
439
|
+
sudoReason: "Package management requires root",
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
toolName: "patch_unattended_audit",
|
|
443
|
+
sudo: "always",
|
|
444
|
+
sudoReason: "Package management requires root",
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
toolName: "patch_integrity_check",
|
|
448
|
+
sudo: "always",
|
|
449
|
+
sudoReason: "Package management requires root",
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
toolName: "patch_kernel_audit",
|
|
453
|
+
sudo: "always",
|
|
454
|
+
sudoReason: "Package management requires root",
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
toolName: "patch_vulnerability_intel",
|
|
458
|
+
sudo: "never",
|
|
459
|
+
sudoReason: "CVE lookup and package scanning do not require root",
|
|
460
|
+
},
|
|
461
|
+
// ── Secrets management tools ──────────────────────────────────────────
|
|
462
|
+
{
|
|
463
|
+
toolName: "secrets_scan",
|
|
464
|
+
sudo: "never",
|
|
465
|
+
sudoReason: "Scans filesystem for secrets using grep/find as current user",
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
toolName: "secrets_env_audit",
|
|
469
|
+
sudo: "never",
|
|
470
|
+
sudoReason: "Audits environment variables and .env files as current user",
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
toolName: "secrets_ssh_key_sprawl",
|
|
474
|
+
sudo: "never",
|
|
475
|
+
sudoReason: "Finds SSH keys and checks permissions as current user",
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
toolName: "secrets_git_history_scan",
|
|
479
|
+
sudo: "never",
|
|
480
|
+
sudoReason: "Scans git repository history as current user",
|
|
481
|
+
},
|
|
482
|
+
// ── Incident response tools ───────────────────────────────────────────
|
|
483
|
+
{
|
|
484
|
+
toolName: "incident_response",
|
|
485
|
+
sudo: "conditional",
|
|
486
|
+
sudoReason: "collect action requires root for full system access; ioc_scan benefits from root; timeline works as user",
|
|
487
|
+
},
|
|
488
|
+
// ── Meta tools ────────────────────────────────────────────────────────
|
|
489
|
+
{
|
|
490
|
+
toolName: "defense_check_tools",
|
|
491
|
+
sudo: "conditional",
|
|
492
|
+
sudoReason: "Tool checks are unprivileged; install_missing uses sudo",
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
toolName: "defense_workflow",
|
|
496
|
+
sudo: "conditional",
|
|
497
|
+
sudoReason: "suggest action is unprivileged; run action may include commands that require root",
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
toolName: "defense_change_history",
|
|
501
|
+
sudo: "never",
|
|
502
|
+
sudoReason: "Reads in-memory changelog without system access",
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
toolName: "defense_security_posture",
|
|
506
|
+
sudo: "conditional",
|
|
507
|
+
sudoReason: "score/dashboard may invoke checks that benefit from root; trend is unprivileged",
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
toolName: "defense_scheduled_audit",
|
|
511
|
+
sudo: "conditional",
|
|
512
|
+
sudoReason: "create/remove actions require root for systemd/cron; list/history are unprivileged",
|
|
513
|
+
},
|
|
514
|
+
// ── Sudo management tools ─────────────────────────────────────────────
|
|
515
|
+
{
|
|
516
|
+
toolName: "sudo_elevate",
|
|
517
|
+
sudo: "never",
|
|
518
|
+
tags: ["bypass-preflight"],
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
toolName: "sudo_elevate_gui",
|
|
522
|
+
sudo: "never",
|
|
523
|
+
tags: ["bypass-preflight"],
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
toolName: "sudo_status",
|
|
527
|
+
sudo: "never",
|
|
528
|
+
tags: ["bypass-preflight"],
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
toolName: "sudo_drop",
|
|
532
|
+
sudo: "never",
|
|
533
|
+
tags: ["bypass-preflight"],
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
toolName: "sudo_extend",
|
|
537
|
+
sudo: "never",
|
|
538
|
+
tags: ["bypass-preflight"],
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
toolName: "preflight_batch_check",
|
|
542
|
+
sudo: "never",
|
|
543
|
+
sudoReason: "Pre-flight checks run without elevation — they only inspect requirements",
|
|
544
|
+
tags: ["bypass-preflight"],
|
|
545
|
+
},
|
|
546
|
+
// ── Supply chain security tools ───────────────────────────────────────
|
|
547
|
+
{
|
|
548
|
+
toolName: "supply_chain",
|
|
549
|
+
sudo: "conditional",
|
|
550
|
+
sudoReason: "sbom/verify actions work without root; sign action may need credentials",
|
|
551
|
+
},
|
|
552
|
+
// ── Drift detection tools ─────────────────────────────────────────────
|
|
553
|
+
{
|
|
554
|
+
toolName: "drift_baseline",
|
|
555
|
+
sudo: "never",
|
|
556
|
+
sudoReason: "Hashes files and captures state without root",
|
|
557
|
+
},
|
|
558
|
+
// ── Zero-trust network tools ──────────────────────────────────────────
|
|
559
|
+
{
|
|
560
|
+
toolName: "zero_trust",
|
|
561
|
+
sudo: "conditional",
|
|
562
|
+
sudoReason: "wireguard/wg_peers/microsegment require root; mtls cert generation does not",
|
|
563
|
+
},
|
|
564
|
+
// ── eBPF tools ────────────────────────────────────────────────────────
|
|
565
|
+
{
|
|
566
|
+
toolName: "ebpf_list_programs",
|
|
567
|
+
sudo: "always",
|
|
568
|
+
sudoReason: "eBPF program listing requires root",
|
|
569
|
+
capabilities: ["CAP_SYS_ADMIN"],
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
toolName: "ebpf_falco",
|
|
573
|
+
sudo: "conditional",
|
|
574
|
+
sudoReason: "status/events may work without root; deploy_rules requires root",
|
|
575
|
+
},
|
|
576
|
+
// ── Application hardening tools ───────────────────────────────────────
|
|
577
|
+
{
|
|
578
|
+
toolName: "app_harden",
|
|
579
|
+
sudo: "conditional",
|
|
580
|
+
sudoReason: "audit/recommend are unprivileged; firewall/systemd actions require root",
|
|
581
|
+
},
|
|
582
|
+
];
|
|
583
|
+
/**
|
|
584
|
+
* Default enhanced manifests that overlay sudo/privilege requirements
|
|
585
|
+
* on top of the legacy-migrated entries.
|
|
586
|
+
*/
|
|
587
|
+
export const DEFAULT_MANIFESTS = SUDO_OVERLAYS.map((o) => ({
|
|
588
|
+
toolName: o.toolName,
|
|
589
|
+
requiredBinaries: [], // merged from legacy during initialization
|
|
590
|
+
sudo: o.sudo,
|
|
591
|
+
sudoReason: o.sudoReason,
|
|
592
|
+
capabilities: o.capabilities,
|
|
593
|
+
tags: o.tags,
|
|
594
|
+
category: inferCategory(o.toolName),
|
|
595
|
+
}));
|
|
596
|
+
// ── Initialization ───────────────────────────────────────────────────────────
|
|
597
|
+
/**
|
|
598
|
+
* Merge two optional tag arrays, deduplicating values.
|
|
599
|
+
*/
|
|
600
|
+
function mergeTags(a, b) {
|
|
601
|
+
if (!a && !b)
|
|
602
|
+
return undefined;
|
|
603
|
+
const set = new Set([...(a ?? []), ...(b ?? [])]);
|
|
604
|
+
return Array.from(set);
|
|
605
|
+
}
|
|
606
|
+
/** Guard to prevent redundant re-initialization */
|
|
607
|
+
let _registryInitialized = false;
|
|
608
|
+
/**
|
|
609
|
+
* Initialize the tool registry by:
|
|
610
|
+
*
|
|
611
|
+
* 1. Creating (or reusing) the singleton
|
|
612
|
+
* 2. Migrating from legacy `TOOL_DEPENDENCIES`
|
|
613
|
+
* 3. Overlaying `DEFAULT_MANIFESTS` — merging privilege metadata while
|
|
614
|
+
* preserving binary requirements from the legacy data
|
|
615
|
+
* 4. Returning the populated registry
|
|
616
|
+
*
|
|
617
|
+
* Safe to call multiple times; subsequent calls return immediately
|
|
618
|
+
* without re-running migration or overlay logic.
|
|
619
|
+
*/
|
|
620
|
+
export function initializeRegistry() {
|
|
621
|
+
const registry = ToolRegistry.instance();
|
|
622
|
+
// Guard: skip re-initialization if already done
|
|
623
|
+
if (_registryInitialized)
|
|
624
|
+
return registry;
|
|
625
|
+
_registryInitialized = true;
|
|
626
|
+
// Step 1 — Migrate all legacy tool dependencies (binary requirements)
|
|
627
|
+
migrateFromLegacy(registry);
|
|
628
|
+
// Step 2 — Overlay DEFAULT_MANIFESTS with merge semantics
|
|
629
|
+
for (const overlay of DEFAULT_MANIFESTS) {
|
|
630
|
+
const existing = registry.getManifest(overlay.toolName);
|
|
631
|
+
if (existing) {
|
|
632
|
+
// Merge: keep binary requirements from legacy, overlay sudo + meta
|
|
633
|
+
registry.register({
|
|
634
|
+
...existing,
|
|
635
|
+
sudo: overlay.sudo,
|
|
636
|
+
sudoReason: overlay.sudoReason ?? existing.sudoReason,
|
|
637
|
+
capabilities: overlay.capabilities ?? existing.capabilities,
|
|
638
|
+
tags: mergeTags(existing.tags, overlay.tags),
|
|
639
|
+
// Prefer the overlay category only when the existing one is missing
|
|
640
|
+
category: existing.category ?? overlay.category,
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
// No legacy entry — register overlay as-is
|
|
645
|
+
registry.register(overlay);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return registry;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Reset the initialization guard (for testing purposes).
|
|
652
|
+
* @internal
|
|
653
|
+
*/
|
|
654
|
+
export function resetRegistryInitialization() {
|
|
655
|
+
_registryInitialized = false;
|
|
656
|
+
}
|