defense-mcp-server 0.7.0 → 0.7.2
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 +43 -6
- package/LICENSE +1 -1
- package/README.md +16 -13
- package/build/core/auto-installer.d.ts +1 -1
- package/build/core/auto-installer.js +5 -5
- package/build/core/backup-manager.d.ts +1 -1
- package/build/core/backup-manager.js +2 -2
- package/build/core/changelog.d.ts +1 -1
- package/build/core/changelog.js +1 -1
- package/build/core/command-allowlist.js +3 -3
- package/build/core/config.d.ts +7 -7
- package/build/core/config.d.ts.map +1 -1
- package/build/core/config.js +27 -27
- package/build/core/dependency-validator.d.ts +2 -2
- package/build/core/dependency-validator.js +5 -5
- package/build/core/distro-adapter.d.ts +1 -1
- package/build/core/distro-adapter.js +1 -1
- package/build/core/encrypted-state.d.ts +5 -5
- package/build/core/encrypted-state.js +7 -7
- package/build/core/executor.d.ts.map +1 -1
- package/build/core/executor.js +34 -13
- package/build/core/installer.d.ts +4 -1
- package/build/core/installer.d.ts.map +1 -1
- package/build/core/installer.js +33 -9
- package/build/core/logger.d.ts +1 -1
- package/build/core/logger.js +2 -2
- package/build/core/pam-utils.d.ts +233 -0
- package/build/core/pam-utils.d.ts.map +1 -0
- package/build/core/pam-utils.js +626 -0
- package/build/core/privilege-manager.d.ts.map +1 -1
- package/build/core/privilege-manager.js +4 -0
- package/build/core/rate-limiter.d.ts +3 -3
- package/build/core/rate-limiter.js +6 -6
- package/build/core/rollback.js +1 -1
- package/build/core/safeguards.d.ts.map +1 -1
- package/build/core/safeguards.js +17 -2
- package/build/core/spawn-safe.js +1 -1
- package/build/core/tool-wrapper.d.ts +2 -2
- package/build/core/tool-wrapper.js +2 -2
- package/build/index.js +3 -3
- package/build/tools/access-control.d.ts +1 -1
- package/build/tools/access-control.d.ts.map +1 -1
- package/build/tools/access-control.js +127 -101
- package/build/tools/api-security.d.ts +1 -1
- package/build/tools/api-security.js +1 -1
- package/build/tools/app-hardening.d.ts +1 -1
- package/build/tools/app-hardening.js +1 -1
- package/build/tools/backup.d.ts +1 -1
- package/build/tools/backup.js +3 -3
- package/build/tools/cloud-security.d.ts +1 -1
- package/build/tools/cloud-security.js +1 -1
- package/build/tools/compliance.d.ts +1 -1
- package/build/tools/compliance.js +1 -1
- package/build/tools/container-security.d.ts +1 -1
- package/build/tools/container-security.js +2 -2
- package/build/tools/deception.d.ts +1 -1
- package/build/tools/deception.js +2 -2
- package/build/tools/dns-security.d.ts +1 -1
- package/build/tools/dns-security.js +3 -3
- package/build/tools/drift-detection.d.ts +2 -1
- package/build/tools/drift-detection.d.ts.map +1 -1
- package/build/tools/drift-detection.js +18 -2
- package/build/tools/encryption.d.ts +1 -1
- package/build/tools/encryption.js +2 -2
- package/build/tools/firewall.d.ts +1 -1
- package/build/tools/firewall.js +1 -1
- package/build/tools/hardening.d.ts +1 -1
- package/build/tools/hardening.js +4 -4
- package/build/tools/incident-response.d.ts +1 -1
- package/build/tools/incident-response.js +3 -3
- package/build/tools/integrity.d.ts +1 -1
- package/build/tools/integrity.js +3 -3
- package/build/tools/logging.d.ts +1 -1
- package/build/tools/logging.js +2 -2
- package/build/tools/malware.d.ts +1 -1
- package/build/tools/malware.js +2 -2
- package/build/tools/meta.js +23 -23
- package/build/tools/network-defense.d.ts +1 -1
- package/build/tools/network-defense.js +1 -1
- package/build/tools/patch-management.js +1 -1
- package/build/tools/process-security.d.ts +1 -1
- package/build/tools/process-security.js +1 -1
- package/build/tools/reporting.d.ts +2 -1
- package/build/tools/reporting.d.ts.map +1 -1
- package/build/tools/reporting.js +18 -2
- package/build/tools/secrets.d.ts +1 -1
- package/build/tools/secrets.js +1 -1
- package/build/tools/siem-integration.d.ts +3 -1
- package/build/tools/siem-integration.d.ts.map +1 -1
- package/build/tools/siem-integration.js +19 -2
- package/build/tools/sudo-management.d.ts +1 -1
- package/build/tools/sudo-management.js +9 -9
- package/build/tools/threat-intel.d.ts +1 -1
- package/build/tools/threat-intel.js +3 -3
- package/build/tools/vulnerability-management.d.ts +1 -1
- package/build/tools/vulnerability-management.js +2 -2
- package/build/tools/waf.d.ts +1 -1
- package/build/tools/waf.js +1 -1
- package/build/tools/wireless-security.d.ts +1 -1
- package/build/tools/wireless-security.js +2 -2
- package/build/tools/zero-trust-network.js +1 -1
- package/docs/SAFEGUARDS.md +20 -20
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,43 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [0.7.1] — 2026-03-14
|
|
10
|
+
|
|
11
|
+
### v0.7.1 — Critical PAM Hardening Fix
|
|
12
|
+
|
|
13
|
+
#### Security Fix
|
|
14
|
+
- **CRITICAL**: Fixed `pam_configure` action corrupting `/etc/pam.d/common-auth` — sed commands stripped whitespace separators between PAM fields, breaking ALL authentication system-wide (required GRUB recovery to fix)
|
|
15
|
+
- **CRITICAL**: Fixed `[success=N]` jump count not being updated after faillock rule insertion — would cause authentication denial on Debian/Ubuntu systems
|
|
16
|
+
|
|
17
|
+
#### New Module: `src/core/pam-utils.ts`
|
|
18
|
+
- Safe in-memory PAM config parser/serializer replacing fragile sed-based manipulation
|
|
19
|
+
- `parsePamConfig()` — Lossless parser handling comments, blanks, `@include`, bracket-style controls
|
|
20
|
+
- `serializePamConfig()` — Serializer with proper formatting (matching `pam-auth-update` canonical format)
|
|
21
|
+
- `validatePamConfig()` — Triple validation: field formatting, module existence, and `[success=N]` jump count correctness
|
|
22
|
+
- `adjustJumpCounts()` — Automatically updates bracket-control jump counts when rules are inserted/removed
|
|
23
|
+
- Manipulation helpers: `removeModuleRules()`, `insertBeforeModule()`, `insertAfterModule()` with pamType filter
|
|
24
|
+
- Sudo-aware I/O: `readPamFile()`, `writePamFile()` (atomic via `sudo install`), `backupPamFile()`, `restorePamFile()`
|
|
25
|
+
|
|
26
|
+
#### Safety Layers (Defense-in-Depth)
|
|
27
|
+
- Mandatory backup before any PAM file modification
|
|
28
|
+
- In-memory validation before writing (catches corrupted fields, missing pam_unix.so, wrong jump counts)
|
|
29
|
+
- Atomic file write using `sudo install -m 644 -o root -g root` (no partial state)
|
|
30
|
+
- Post-write re-read validation
|
|
31
|
+
- Auto-rollback on ANY failure (restores from backup automatically)
|
|
32
|
+
|
|
33
|
+
#### Security Review Remediations
|
|
34
|
+
- Fixed partial write state on chmod/chown failure (atomic `sudo install`)
|
|
35
|
+
- Fixed temp file symlink race (secure `mkdtempSync`)
|
|
36
|
+
- Fixed insert helpers matching by module only (added pamType filter)
|
|
37
|
+
- Fixed `backupPamFile` mutating BackupEntry internal state
|
|
38
|
+
- Fixed `restorePamFile` leaking PAM content to stdout via `tee`
|
|
39
|
+
- Added PAM modification warning to SafeguardRegistry
|
|
40
|
+
|
|
41
|
+
#### Testing
|
|
42
|
+
- 63 new tests in `tests/core/pam-utils.test.ts` covering parser, serializer, validator, jump count adjustment, manipulation helpers, and full faillock integration flow
|
|
43
|
+
- 7 new tests in `tests/tools/access-control.test.ts` for pam_configure regression testing
|
|
44
|
+
- Critical regression test: verifies concatenated PAM fields (the original lockout bug) can never be produced
|
|
45
|
+
|
|
9
46
|
## [0.7.0] — 2026-03-12
|
|
10
47
|
|
|
11
48
|
### v0.7.0 — Tool Consolidation & Sudo Hardening Overhaul
|
|
@@ -199,13 +236,13 @@ Major security remediation release consolidating 157 tools down to 78 action-bas
|
|
|
199
236
|
|
|
200
237
|
- **Fix 1.1: Password Buffer Pipeline** — Sudo password now stored in a zeroable `Buffer` (not V8-interned strings). Auto-expires after configurable timeout. Temp files overwritten with random bytes before deletion.
|
|
201
238
|
- **Fix 1.2: Command Allowlist** — All commands executed via `spawn()` are resolved against a strict allowlist of known-safe binaries. Unknown binaries are rejected before execution. Paths resolved to absolute at startup.
|
|
202
|
-
- **Fix 1.3: Auto-Install Hardening** — `
|
|
239
|
+
- **Fix 1.3: Auto-Install Hardening** — `DEFENSE_MCP_AUTO_INSTALL` now defaults to `false`. When enabled, only packages from the `DEFENSIVE_TOOLS` catalog are installable — arbitrary package names are blocked.
|
|
203
240
|
- **Fix 1.4: Secure File Permissions** — All state files (`changelog.json`, `rollback-state.json`, backups, quarantine) created with `0o600`/`0o700` permissions. Existing directories hardened at startup via `hardenDirPermissions()`.
|
|
204
241
|
|
|
205
242
|
### Test Infrastructure (Phase 2)
|
|
206
243
|
|
|
207
244
|
- **Fix 2.1: Vitest Test Suite** — 221 tests across 6 test files covering sanitizer, config, command-allowlist, secure-fs, changelog, and safeguards modules. All tests pass with zero failures.
|
|
208
|
-
- **Fix 2.2: Backup/Rollback Unification** — `BackupManager` and `RollbackManager` consolidated under `~/.
|
|
245
|
+
- **Fix 2.2: Backup/Rollback Unification** — `BackupManager` and `RollbackManager` consolidated under `~/.defense-mcp/` with consistent secure file permissions.
|
|
209
246
|
- **Fix 2.3: Safeguards Real Blockers** — `SafeguardRegistry.checkSafety()` now produces real blocking conditions, not just advisory warnings.
|
|
210
247
|
- **Fix 2.4: spawn-safe.ts Circular Dependency** — Extracted safe spawn helper to break circular dependency between `executor.ts` and `sudo-session.ts`.
|
|
211
248
|
|
|
@@ -306,8 +343,8 @@ Adds a comprehensive pre-flight validation system that automatically checks depe
|
|
|
306
343
|
- `formatStatusMessage()` — compact one-line status for prepending to tool output
|
|
307
344
|
|
|
308
345
|
#### New Environment Variables
|
|
309
|
-
- `
|
|
310
|
-
- `
|
|
346
|
+
- `DEFENSE_MCP_PREFLIGHT` (default: `true`) — enable/disable pre-flight checks entirely
|
|
347
|
+
- `DEFENSE_MCP_PREFLIGHT_BANNERS` (default: `true`) — show pre-flight status banners in tool output
|
|
311
348
|
|
|
312
349
|
### Changed
|
|
313
350
|
|
|
@@ -448,7 +485,7 @@ Major release expanding the server from 69 tools across 12 categories to 130+ to
|
|
|
448
485
|
- All detection errors are caught gracefully and converted to warnings rather than failures
|
|
449
486
|
|
|
450
487
|
#### `src/core/backup-manager.ts` — BackupManager
|
|
451
|
-
- Manages file backups with manifest tracking under `~/.
|
|
488
|
+
- Manages file backups with manifest tracking under `~/.defense-mcp-backups/`
|
|
452
489
|
- Each backup entry has a UUID, original path, backup path, timestamp, and size
|
|
453
490
|
- `manifest.json` maintains the full backup inventory for list and restore operations
|
|
454
491
|
- `backup(filePath)` — creates timestamped copy and adds to manifest, returns UUID
|
|
@@ -458,7 +495,7 @@ Major release expanding the server from 69 tools across 12 categories to 130+ to
|
|
|
458
495
|
|
|
459
496
|
#### `src/core/rollback.ts` — RollbackManager
|
|
460
497
|
- Singleton that tracks system changes within and across sessions
|
|
461
|
-
- State persisted to `~/.
|
|
498
|
+
- State persisted to `~/.defense-mcp/rollback-state.json`
|
|
462
499
|
- Supports four change types: `file` (backup path), `sysctl` (previous value), `service` (previous state), `firewall` (rollback command)
|
|
463
500
|
- `rollback(operationId)` — reverses all changes for a specific operation in reverse order
|
|
464
501
|
- `rollbackSession(sessionId)` — reverses all changes from the current session
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026
|
|
3
|
+
Copyright (c) 2026 Defense MCP Server Contributors
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
A Model Context Protocol (MCP) server that gives AI assistants access to **94 defensive security tools** on Linux. Connect it to Claude Desktop, Cursor, or any MCP-compatible client to harden systems, manage firewalls, scan for vulnerabilities, and enforce compliance — all through natural language conversation.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Why I Made This
|
|
6
|
+
Basically I'm a total noob when it comes to really serious system hardening so I thought I'd test the latest LLM models and see how far I could get. Turns out they're pretty helpful! I got tired of hardening my new systems by hand every time I spun up a new one so I made this MCP server to make it pretty easy. I jam packed as many security tools as I could into this thing so be prepared to burn tokens using it. Hopefully it helps you about half as much as its helped me.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
## So What It Does
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
This server exposes Linux security tools as MCP tools that an AI assistant can invoke on your behalf. Instead of memorizing command syntax for dozens of security utilities, you describe what you want in plain English and the assistant calls the right tool with the right parameters. Sounds pretty good right!
|
|
11
|
+
|
|
12
|
+
Here are the tools:
|
|
10
13
|
|
|
11
14
|
| Module | What It Does |
|
|
12
15
|
|--------|-------------|
|
|
@@ -75,7 +78,7 @@ You don't need to pre-install every security tool. The server automatically dete
|
|
|
75
78
|
|
|
76
79
|
To disable auto-installation entirely, run with:
|
|
77
80
|
```bash
|
|
78
|
-
|
|
81
|
+
DEFENSE_MCP_AUTO_INSTALL=false node build/index.js
|
|
79
82
|
```
|
|
80
83
|
|
|
81
84
|
## Requirements
|
|
@@ -183,18 +186,18 @@ Configuration is via environment variables. All have secure defaults:
|
|
|
183
186
|
|
|
184
187
|
| Variable | Default | Description |
|
|
185
188
|
|----------|---------|-------------|
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
189
|
+
| `DEFENSE_MCP_DRY_RUN` | `true` | Preview changes without applying |
|
|
190
|
+
| `DEFENSE_MCP_REQUIRE_CONFIRMATION` | `true` | Require confirmation for destructive actions |
|
|
191
|
+
| `DEFENSE_MCP_ALLOWED_DIRS` | `/tmp,/home,/var/log` | Directories the server can access |
|
|
192
|
+
| `DEFENSE_MCP_LOG_LEVEL` | `info` | Log verbosity (debug/info/warn/error) |
|
|
193
|
+
| `DEFENSE_MCP_BACKUP_ENABLED` | `true` | Auto-backup before system changes |
|
|
194
|
+
| `DEFENSE_MCP_AUTO_INSTALL` | `true` | Auto-install missing tool dependencies |
|
|
195
|
+
| `DEFENSE_MCP_PREFLIGHT` | `true` | Enable pre-flight dependency checks |
|
|
196
|
+
| `DEFENSE_MCP_PREFLIGHT_BANNERS` | `true` | Show pre-flight status in tool output |
|
|
194
197
|
|
|
195
198
|
To apply changes for real (not just preview), set:
|
|
196
199
|
```bash
|
|
197
|
-
|
|
200
|
+
DEFENSE_MCP_DRY_RUN=false node build/index.js
|
|
198
201
|
```
|
|
199
202
|
|
|
200
203
|
## Security
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles installation of missing dependencies across system package managers
|
|
5
5
|
* (apt, dnf, yum, pacman, apk, zypper, brew), pip, and npm. This module is
|
|
6
6
|
* part of the pre-flight validation pipeline and is invoked when
|
|
7
|
-
* `
|
|
7
|
+
* `DEFENSE_MCP_AUTO_INSTALL=true`.
|
|
8
8
|
*
|
|
9
9
|
* Design constraints:
|
|
10
10
|
* - Uses `execFileSafe` from `spawn-safe.ts` (NOT the executor) to avoid
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles installation of missing dependencies across system package managers
|
|
5
5
|
* (apt, dnf, yum, pacman, apk, zypper, brew), pip, and npm. This module is
|
|
6
6
|
* part of the pre-flight validation pipeline and is invoked when
|
|
7
|
-
* `
|
|
7
|
+
* `DEFENSE_MCP_AUTO_INSTALL=true`.
|
|
8
8
|
*
|
|
9
9
|
* Design constraints:
|
|
10
10
|
* - Uses `execFileSafe` from `spawn-safe.ts` (NOT the executor) to avoid
|
|
@@ -310,7 +310,7 @@ export class AutoInstaller {
|
|
|
310
310
|
type: "binary",
|
|
311
311
|
method: "skipped",
|
|
312
312
|
success: false,
|
|
313
|
-
message: "Auto-install is disabled (set
|
|
313
|
+
message: "Auto-install is disabled (set DEFENSE_MCP_AUTO_INSTALL=true to enable)",
|
|
314
314
|
});
|
|
315
315
|
}
|
|
316
316
|
for (const dep of missingPython ?? []) {
|
|
@@ -319,7 +319,7 @@ export class AutoInstaller {
|
|
|
319
319
|
type: "python-module",
|
|
320
320
|
method: "skipped",
|
|
321
321
|
success: false,
|
|
322
|
-
message: "Auto-install is disabled (set
|
|
322
|
+
message: "Auto-install is disabled (set DEFENSE_MCP_AUTO_INSTALL=true to enable)",
|
|
323
323
|
});
|
|
324
324
|
}
|
|
325
325
|
for (const dep of missingNpm ?? []) {
|
|
@@ -328,7 +328,7 @@ export class AutoInstaller {
|
|
|
328
328
|
type: "npm-package",
|
|
329
329
|
method: "skipped",
|
|
330
330
|
success: false,
|
|
331
|
-
message: "Auto-install is disabled (set
|
|
331
|
+
message: "Auto-install is disabled (set DEFENSE_MCP_AUTO_INSTALL=true to enable)",
|
|
332
332
|
});
|
|
333
333
|
}
|
|
334
334
|
for (const dep of missingLibraries ?? []) {
|
|
@@ -337,7 +337,7 @@ export class AutoInstaller {
|
|
|
337
337
|
type: "library",
|
|
338
338
|
method: "skipped",
|
|
339
339
|
success: false,
|
|
340
|
-
message: "Auto-install is disabled (set
|
|
340
|
+
message: "Auto-install is disabled (set DEFENSE_MCP_AUTO_INSTALL=true to enable)",
|
|
341
341
|
});
|
|
342
342
|
}
|
|
343
343
|
return {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* BackupManager — manages file backups with manifest tracking.
|
|
3
3
|
*
|
|
4
|
-
* Backups are stored under ~/.
|
|
4
|
+
* Backups are stored under ~/.defense-mcp/backups/ with timestamped filenames.
|
|
5
5
|
* A manifest.json tracks all backups for listing and restore operations.
|
|
6
6
|
*/
|
|
7
7
|
export interface BackupEntry {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* BackupManager — manages file backups with manifest tracking.
|
|
3
3
|
*
|
|
4
|
-
* Backups are stored under ~/.
|
|
4
|
+
* Backups are stored under ~/.defense-mcp/backups/ with timestamped filenames.
|
|
5
5
|
* A manifest.json tracks all backups for listing and restore operations.
|
|
6
6
|
*/
|
|
7
7
|
import { existsSync, readFileSync, unlinkSync, statSync, lstatSync, } from "node:fs";
|
|
@@ -59,7 +59,7 @@ export class BackupManager {
|
|
|
59
59
|
backupDir;
|
|
60
60
|
manifestPath;
|
|
61
61
|
constructor(backupDir) {
|
|
62
|
-
this.backupDir = backupDir ?? join(homedir(), ".
|
|
62
|
+
this.backupDir = backupDir ?? join(homedir(), ".defense-mcp", "backups");
|
|
63
63
|
this.manifestPath = join(this.backupDir, "manifest.json");
|
|
64
64
|
}
|
|
65
65
|
/** Ensure backup directory exists. */
|
|
@@ -59,7 +59,7 @@ export declare function logChange(entry: ChangeEntry): void;
|
|
|
59
59
|
export declare function getChangelog(limit?: number): ChangeEntry[];
|
|
60
60
|
/**
|
|
61
61
|
* Creates a backup copy of a file using the unified BackupManager.
|
|
62
|
-
* The backup is tracked in the manifest at ~/.
|
|
62
|
+
* The backup is tracked in the manifest at ~/.defense-mcp/backups/manifest.json.
|
|
63
63
|
*
|
|
64
64
|
* @param filePath Absolute path to the file to back up
|
|
65
65
|
* @returns Path to the backup file
|
package/build/core/changelog.js
CHANGED
|
@@ -97,7 +97,7 @@ export function getChangelog(limit) {
|
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
99
|
* Creates a backup copy of a file using the unified BackupManager.
|
|
100
|
-
* The backup is tracked in the manifest at ~/.
|
|
100
|
+
* The backup is tracked in the manifest at ~/.defense-mcp/backups/manifest.json.
|
|
101
101
|
*
|
|
102
102
|
* @param filePath Absolute path to the file to back up
|
|
103
103
|
* @returns Path to the backup file
|
|
@@ -324,10 +324,10 @@ let initialized = false;
|
|
|
324
324
|
* mitigating TOCTOU (time-of-check-time-of-use) attacks where a binary is
|
|
325
325
|
* replaced between startup resolution and runtime execution.
|
|
326
326
|
*
|
|
327
|
-
* Configurable via
|
|
327
|
+
* Configurable via DEFENSE_MCP_RUNTIME_PATH_VERIFY env var.
|
|
328
328
|
* Default: true (verify at runtime). Set to "false" to disable for performance.
|
|
329
329
|
*/
|
|
330
|
-
let runtimePathVerification = process.env.
|
|
330
|
+
let runtimePathVerification = process.env.DEFENSE_MCP_RUNTIME_PATH_VERIFY !== "false";
|
|
331
331
|
// Populate the map immediately so `isAllowlisted()` works before init
|
|
332
332
|
for (const entry of ALLOWLIST_DEFINITIONS) {
|
|
333
333
|
allowlistMap.set(entry.binary, entry);
|
|
@@ -349,7 +349,7 @@ export function initializeAllowlist() {
|
|
|
349
349
|
// Clear reverse map for re-initialization
|
|
350
350
|
reversePathMap.clear();
|
|
351
351
|
// Re-read runtime path verification setting on re-init
|
|
352
|
-
runtimePathVerification = process.env.
|
|
352
|
+
runtimePathVerification = process.env.DEFENSE_MCP_RUNTIME_PATH_VERIFY !== "false";
|
|
353
353
|
for (const entry of ALLOWLIST_DEFINITIONS) {
|
|
354
354
|
entry.resolvedPath = undefined;
|
|
355
355
|
entry.resolvedInode = undefined;
|
package/build/core/config.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Known defensive tools that support per-tool timeout overrides
|
|
3
|
-
* via
|
|
3
|
+
* via DEFENSE_MCP_TIMEOUT_<TOOL> environment variables.
|
|
4
4
|
*/
|
|
5
5
|
export declare const KNOWN_TOOLS: readonly ["lynis", "aide", "clamav", "oscap", "snort", "suricata", "rkhunter", "chkrootkit", "tcpdump", "auditd", "nmap", "fail2ban-client", "debsums", "yara"];
|
|
6
6
|
export type KnownTool = (typeof KNOWN_TOOLS)[number];
|
|
7
7
|
/**
|
|
8
|
-
* Configuration interface for the
|
|
8
|
+
* Configuration interface for the Defense MCP Server.
|
|
9
9
|
* All values are derived from environment variables with sensible defaults.
|
|
10
10
|
*/
|
|
11
11
|
export interface DefenseConfig {
|
|
@@ -21,7 +21,7 @@ export interface DefenseConfig {
|
|
|
21
21
|
* SECURITY (CICD-014): Dry-run mode — when true, modifying operations preview
|
|
22
22
|
* commands without executing them. Defaults to `true` so the server operates
|
|
23
23
|
* in a safe, read-only mode until explicitly opted out via
|
|
24
|
-
*
|
|
24
|
+
* DEFENSE_MCP_DRY_RUN=false. This prevents accidental system modifications.
|
|
25
25
|
*/
|
|
26
26
|
dryRun: boolean;
|
|
27
27
|
/** Path to the changelog JSON file */
|
|
@@ -32,7 +32,7 @@ export interface DefenseConfig {
|
|
|
32
32
|
* SECURITY (CICD-014): Whether to create backups before modifying files.
|
|
33
33
|
* Defaults to `true` — every file modification is backed up first so that
|
|
34
34
|
* changes can be rolled back if needed. Disable only in CI/test environments
|
|
35
|
-
* via
|
|
35
|
+
* via DEFENSE_MCP_BACKUP_ENABLED=false.
|
|
36
36
|
*/
|
|
37
37
|
backupEnabled: boolean;
|
|
38
38
|
/** Whether to auto-install missing tools */
|
|
@@ -44,7 +44,7 @@ export interface DefenseConfig {
|
|
|
44
44
|
* actions. Defaults to `true` — the server will request explicit confirmation
|
|
45
45
|
* before executing operations that modify system state. Disable only when
|
|
46
46
|
* running automated/unattended workflows via
|
|
47
|
-
*
|
|
47
|
+
* DEFENSE_MCP_REQUIRE_CONFIRMATION=false.
|
|
48
48
|
*/
|
|
49
49
|
requireConfirmation: boolean;
|
|
50
50
|
/** Directory for quarantined files */
|
|
@@ -55,9 +55,9 @@ export interface DefenseConfig {
|
|
|
55
55
|
toolTimeouts: Partial<Record<KnownTool, number>>;
|
|
56
56
|
/** Sudo session timeout in milliseconds (default: 15 minutes) */
|
|
57
57
|
sudoSessionTimeout: number;
|
|
58
|
-
/** Command execution timeout in ms (falls back to defaultTimeout; env:
|
|
58
|
+
/** Command execution timeout in ms (falls back to defaultTimeout; env: DEFENSE_MCP_COMMAND_TIMEOUT) */
|
|
59
59
|
commandTimeout: number;
|
|
60
|
-
/** Network operation timeout in ms (default: 30s; env:
|
|
60
|
+
/** Network operation timeout in ms (default: 30s; env: DEFENSE_MCP_NETWORK_TIMEOUT) */
|
|
61
61
|
networkTimeout: number;
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,WAAW,iKAed,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oBAAoB;IACpB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC9C;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,4CAA4C;IAC5C,WAAW,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;OAMG;IACH,mBAAmB,EAAE,OAAO,CAAC;IAC7B,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,WAAW,iKAed,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oBAAoB;IACpB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC9C;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,4CAA4C;IAC5C,WAAW,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;OAMG;IACH,mBAAmB,EAAE,OAAO,CAAC;IAC7B,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uGAAuG;IACvG,cAAc,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,cAAc,EAAE,MAAM,CAAC;CACxB;AAmGD;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,aAAa,CAQzC;AAwFD;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,aAAa,GACrB,MAAM,CAIR"}
|
package/build/core/config.js
CHANGED
|
@@ -2,7 +2,7 @@ import { homedir } from "node:os";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
/**
|
|
4
4
|
* Known defensive tools that support per-tool timeout overrides
|
|
5
|
-
* via
|
|
5
|
+
* via DEFENSE_MCP_TIMEOUT_<TOOL> environment variables.
|
|
6
6
|
*/
|
|
7
7
|
export const KNOWN_TOOLS = [
|
|
8
8
|
"lynis",
|
|
@@ -50,19 +50,19 @@ function parsePaths(value, defaultValue) {
|
|
|
50
50
|
return paths.filter((p) => {
|
|
51
51
|
// Reject root directory and single-character root-level paths (e.g. "/")
|
|
52
52
|
if (REJECTED_DIRS.has(p) || (p.startsWith("/") && p.length <= 2 && p !== "/" + p.slice(1).replace(/\//g, ""))) {
|
|
53
|
-
console.error(`[
|
|
53
|
+
console.error(`[DEFENSE-MCP] SECURITY: Rejecting overly broad allowedDir '${p}' — ` +
|
|
54
54
|
`granting access to the entire filesystem is not permitted.`);
|
|
55
55
|
return false;
|
|
56
56
|
}
|
|
57
57
|
// Reject any single-character root-level path like "/x"
|
|
58
58
|
if (/^\/[^/]$/.test(p)) {
|
|
59
|
-
console.error(`[
|
|
59
|
+
console.error(`[DEFENSE-MCP] SECURITY: Rejecting overly broad allowedDir '${p}' — ` +
|
|
60
60
|
`single-character root-level paths are not permitted.`);
|
|
61
61
|
return false;
|
|
62
62
|
}
|
|
63
63
|
// Warn about broad directories
|
|
64
64
|
if (BROAD_DIRS.has(p)) {
|
|
65
|
-
console.error(`[
|
|
65
|
+
console.error(`[DEFENSE-MCP] WARNING: allowedDir '${p}' is very broad. ` +
|
|
66
66
|
`Consider using a more specific subdirectory.`);
|
|
67
67
|
}
|
|
68
68
|
return true;
|
|
@@ -80,12 +80,12 @@ function parseLogLevel(value) {
|
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* Reads per-tool timeout overrides from environment variables.
|
|
83
|
-
* Format:
|
|
83
|
+
* Format: DEFENSE_MCP_TIMEOUT_<TOOL> (value in seconds, stored as ms).
|
|
84
84
|
*/
|
|
85
85
|
function parseToolTimeouts() {
|
|
86
86
|
const timeouts = {};
|
|
87
87
|
for (const tool of KNOWN_TOOLS) {
|
|
88
|
-
const envKey = `
|
|
88
|
+
const envKey = `DEFENSE_MCP_TIMEOUT_${tool.toUpperCase()}`;
|
|
89
89
|
const value = process.env[envKey];
|
|
90
90
|
if (value !== undefined) {
|
|
91
91
|
const seconds = parseInt(value, 10);
|
|
@@ -119,8 +119,8 @@ export function getConfig() {
|
|
|
119
119
|
* This is the actual parsing logic, called by the cached `getConfig()` wrapper.
|
|
120
120
|
*/
|
|
121
121
|
function buildConfigFromEnv() {
|
|
122
|
-
const defaultTimeoutSec = parseInt(process.env.
|
|
123
|
-
const maxBufferBytes = parseInt(process.env.
|
|
122
|
+
const defaultTimeoutSec = parseInt(process.env.DEFENSE_MCP_TIMEOUT_DEFAULT ?? "120", 10);
|
|
123
|
+
const maxBufferBytes = parseInt(process.env.DEFENSE_MCP_MAX_OUTPUT_SIZE ?? String(10 * 1024 * 1024), 10);
|
|
124
124
|
const config = {
|
|
125
125
|
defaultTimeout: isNaN(defaultTimeoutSec) || defaultTimeoutSec <= 0
|
|
126
126
|
? 120_000
|
|
@@ -132,26 +132,26 @@ function buildConfigFromEnv() {
|
|
|
132
132
|
// contains sensitive system configuration files (shadow, sudoers, ssh configs).
|
|
133
133
|
// Granting default read/write access to /etc is too permissive. Tools that
|
|
134
134
|
// need /etc access should require explicit configuration via
|
|
135
|
-
//
|
|
136
|
-
allowedDirs: parsePaths(process.env.
|
|
137
|
-
logLevel: parseLogLevel(process.env.
|
|
135
|
+
// DEFENSE_MCP_ALLOWED_DIRS=/tmp,/home,/var/log,/etc
|
|
136
|
+
allowedDirs: parsePaths(process.env.DEFENSE_MCP_ALLOWED_DIRS, "/tmp,/home,/var/log"),
|
|
137
|
+
logLevel: parseLogLevel(process.env.DEFENSE_MCP_LOG_LEVEL),
|
|
138
138
|
// SECURITY (CICD-014): Default to dry-run=true (safe preview mode)
|
|
139
|
-
// Set
|
|
140
|
-
dryRun: process.env.
|
|
141
|
-
changelogPath: expandHome(process.env.
|
|
142
|
-
"~/.
|
|
143
|
-
backupDir: expandHome(process.env.
|
|
139
|
+
// Set DEFENSE_MCP_DRY_RUN=false to enable live system modifications
|
|
140
|
+
dryRun: process.env.DEFENSE_MCP_DRY_RUN !== "false",
|
|
141
|
+
changelogPath: expandHome(process.env.DEFENSE_MCP_CHANGELOG_PATH ??
|
|
142
|
+
"~/.defense-mcp/changelog.json"),
|
|
143
|
+
backupDir: expandHome(process.env.DEFENSE_MCP_BACKUP_DIR ?? "~/.defense-mcp/backups"),
|
|
144
144
|
// SECURITY (CICD-014): Backup before modify — enabled by default
|
|
145
|
-
// Set
|
|
146
|
-
backupEnabled: process.env.
|
|
147
|
-
autoInstall: process.env.
|
|
148
|
-
protectedPaths: parsePaths(process.env.
|
|
149
|
-
requireConfirmation: process.env.
|
|
150
|
-
quarantineDir: expandHome(process.env.
|
|
151
|
-
policyDir: expandHome(process.env.
|
|
145
|
+
// Set DEFENSE_MCP_BACKUP_ENABLED=false only in CI/test environments
|
|
146
|
+
backupEnabled: process.env.DEFENSE_MCP_BACKUP_ENABLED !== "false",
|
|
147
|
+
autoInstall: process.env.DEFENSE_MCP_AUTO_INSTALL === "true",
|
|
148
|
+
protectedPaths: parsePaths(process.env.DEFENSE_MCP_PROTECTED_PATHS, "/boot,/usr/lib/systemd,/usr/bin,/usr/sbin"),
|
|
149
|
+
requireConfirmation: process.env.DEFENSE_MCP_REQUIRE_CONFIRMATION !== "false",
|
|
150
|
+
quarantineDir: expandHome(process.env.DEFENSE_MCP_QUARANTINE_DIR ?? "~/.defense-mcp/quarantine"),
|
|
151
|
+
policyDir: expandHome(process.env.DEFENSE_MCP_POLICY_DIR ?? "~/.defense-mcp/policies"),
|
|
152
152
|
toolTimeouts: parseToolTimeouts(),
|
|
153
153
|
sudoSessionTimeout: (() => {
|
|
154
|
-
const envVal = process.env.
|
|
154
|
+
const envVal = process.env.DEFENSE_MCP_SUDO_TIMEOUT;
|
|
155
155
|
if (envVal) {
|
|
156
156
|
const minutes = parseInt(envVal, 10);
|
|
157
157
|
if (!isNaN(minutes) && minutes > 0)
|
|
@@ -160,17 +160,17 @@ function buildConfigFromEnv() {
|
|
|
160
160
|
return 15 * 60 * 1000; // default: 15 minutes
|
|
161
161
|
})(),
|
|
162
162
|
commandTimeout: (() => {
|
|
163
|
-
const sec = parseInt(process.env.
|
|
163
|
+
const sec = parseInt(process.env.DEFENSE_MCP_COMMAND_TIMEOUT ?? "120", 10);
|
|
164
164
|
return isNaN(sec) || sec <= 0 ? 120_000 : sec * 1000;
|
|
165
165
|
})(),
|
|
166
166
|
networkTimeout: (() => {
|
|
167
|
-
const sec = parseInt(process.env.
|
|
167
|
+
const sec = parseInt(process.env.DEFENSE_MCP_NETWORK_TIMEOUT ?? "30", 10);
|
|
168
168
|
return isNaN(sec) || sec <= 0 ? 30_000 : sec * 1000;
|
|
169
169
|
})(),
|
|
170
170
|
};
|
|
171
171
|
// Warn when dry-run is active so operators know no changes will be applied
|
|
172
172
|
if (config.dryRun) {
|
|
173
|
-
console.error("[
|
|
173
|
+
console.error("[DEFENSE-MCP] DRY_RUN mode is ACTIVE — no changes will be applied");
|
|
174
174
|
}
|
|
175
175
|
return config;
|
|
176
176
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dependency Validator for
|
|
2
|
+
* Dependency Validator for Defense MCP Server.
|
|
3
3
|
*
|
|
4
4
|
* Provides three key capabilities:
|
|
5
5
|
* 1. **Startup validation** — checks all tool dependencies when the server starts
|
|
6
|
-
* and auto-installs missing ones if
|
|
6
|
+
* and auto-installs missing ones if DEFENSE_MCP_AUTO_INSTALL=true
|
|
7
7
|
* 2. **Runtime dependency check** — `ensureDependencies()` can be called before
|
|
8
8
|
* any tool execution to verify (and optionally install) required binaries
|
|
9
9
|
* 3. **Dependency status cache** — avoids redundant `which` calls by caching
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dependency Validator for
|
|
2
|
+
* Dependency Validator for Defense MCP Server.
|
|
3
3
|
*
|
|
4
4
|
* Provides three key capabilities:
|
|
5
5
|
* 1. **Startup validation** — checks all tool dependencies when the server starts
|
|
6
|
-
* and auto-installs missing ones if
|
|
6
|
+
* and auto-installs missing ones if DEFENSE_MCP_AUTO_INSTALL=true
|
|
7
7
|
* 2. **Runtime dependency check** — `ensureDependencies()` can be called before
|
|
8
8
|
* any tool execution to verify (and optionally install) required binaries
|
|
9
9
|
* 3. **Dependency status cache** — avoids redundant `which` calls by caching
|
|
@@ -215,7 +215,7 @@ export async function validateAllDependencies() {
|
|
|
215
215
|
for (const cm of criticalMissing) {
|
|
216
216
|
console.error(`[dep-validator] - ${cm.toolName}: needs ${cm.missingBinaries.join(", ")}`);
|
|
217
217
|
}
|
|
218
|
-
console.error(`[dep-validator] Set
|
|
218
|
+
console.error(`[dep-validator] Set DEFENSE_MCP_AUTO_INSTALL=true to auto-install missing tools`);
|
|
219
219
|
}
|
|
220
220
|
return report;
|
|
221
221
|
}
|
|
@@ -330,7 +330,7 @@ export async function isBinaryInstalled(binary) {
|
|
|
330
330
|
export function formatValidationReport(report) {
|
|
331
331
|
const lines = [];
|
|
332
332
|
lines.push("╔══════════════════════════════════════════════════════════╗");
|
|
333
|
-
lines.push("║
|
|
333
|
+
lines.push("║ Defense MCP — Dependency Validation ║");
|
|
334
334
|
lines.push("╚══════════════════════════════════════════════════════════╝");
|
|
335
335
|
lines.push("");
|
|
336
336
|
lines.push(` Binaries checked: ${report.totalChecked}`);
|
|
@@ -367,7 +367,7 @@ export function formatValidationReport(report) {
|
|
|
367
367
|
lines.push("");
|
|
368
368
|
lines.push(` Auto-install: ${report.autoInstallEnabled ? "ENABLED" : "DISABLED"}`);
|
|
369
369
|
if (!report.autoInstallEnabled && report.missing.length > 0) {
|
|
370
|
-
lines.push(" 💡 Set
|
|
370
|
+
lines.push(" 💡 Set DEFENSE_MCP_AUTO_INSTALL=true to auto-install missing tools");
|
|
371
371
|
}
|
|
372
372
|
lines.push(` Duration: ${report.durationMs}ms`);
|
|
373
373
|
return lines.join("\n");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* DistroAdapter — unified cross-distribution API for the
|
|
2
|
+
* DistroAdapter — unified cross-distribution API for the Defense MCP Server.
|
|
3
3
|
*
|
|
4
4
|
* This module provides a single, cached adapter instance that abstracts away
|
|
5
5
|
* distribution-specific differences in:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* DistroAdapter — unified cross-distribution API for the
|
|
2
|
+
* DistroAdapter — unified cross-distribution API for the Defense MCP Server.
|
|
3
3
|
*
|
|
4
4
|
* This module provides a single, cached adapter instance that abstracts away
|
|
5
5
|
* distribution-specific differences in:
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* policy files, sudo session tokens, and other sensitive state.
|
|
6
6
|
*
|
|
7
7
|
* Key derivation uses PBKDF2 from a configurable secret via the
|
|
8
|
-
* `
|
|
8
|
+
* `DEFENSE_MCP_STATE_KEY` environment variable. If no key is
|
|
9
9
|
* configured, falls back to unencrypted mode with a warning.
|
|
10
10
|
*
|
|
11
11
|
* @module encrypted-state
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
/**
|
|
14
14
|
* Encrypted state storage for sensitive data at rest.
|
|
15
15
|
*
|
|
16
|
-
* Uses AES-256-GCM with PBKDF2-derived keys when `
|
|
16
|
+
* Uses AES-256-GCM with PBKDF2-derived keys when `DEFENSE_MCP_STATE_KEY`
|
|
17
17
|
* is set. Falls back to plaintext JSON when no key is configured.
|
|
18
18
|
*/
|
|
19
19
|
export declare class SecureStateStore {
|
|
20
20
|
private readonly stateDir;
|
|
21
21
|
private readonly secret;
|
|
22
22
|
/**
|
|
23
|
-
* @param stateDir - Directory for state files (default: `/tmp/
|
|
24
|
-
* @param secret - Encryption secret. If omitted, reads from `
|
|
23
|
+
* @param stateDir - Directory for state files (default: `/tmp/defense-mcp/state/`)
|
|
24
|
+
* @param secret - Encryption secret. If omitted, reads from `DEFENSE_MCP_STATE_KEY` env var.
|
|
25
25
|
* Pass empty string or omit to use unencrypted fallback.
|
|
26
26
|
*/
|
|
27
27
|
constructor(stateDir?: string, secret?: string);
|
|
@@ -70,7 +70,7 @@ export declare class SecureStateStore {
|
|
|
70
70
|
* Default singleton SecureStateStore instance.
|
|
71
71
|
*
|
|
72
72
|
* Uses the default state directory and reads the encryption key from
|
|
73
|
-
* the `
|
|
73
|
+
* the `DEFENSE_MCP_STATE_KEY` environment variable.
|
|
74
74
|
*/
|
|
75
75
|
export declare const secureState: SecureStateStore;
|
|
76
76
|
//# sourceMappingURL=encrypted-state.d.ts.map
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* policy files, sudo session tokens, and other sensitive state.
|
|
6
6
|
*
|
|
7
7
|
* Key derivation uses PBKDF2 from a configurable secret via the
|
|
8
|
-
* `
|
|
8
|
+
* `DEFENSE_MCP_STATE_KEY` environment variable. If no key is
|
|
9
9
|
* configured, falls back to unencrypted mode with a warning.
|
|
10
10
|
*
|
|
11
11
|
* @module encrypted-state
|
|
@@ -31,13 +31,13 @@ const PBKDF2_DIGEST = "sha512";
|
|
|
31
31
|
/** Salt length in bytes. */
|
|
32
32
|
const SALT_LENGTH = 16;
|
|
33
33
|
/** Default state directory. */
|
|
34
|
-
const DEFAULT_STATE_DIR = "/tmp/
|
|
34
|
+
const DEFAULT_STATE_DIR = "/tmp/defense-mcp/state/";
|
|
35
35
|
/** File permission: owner read/write only. */
|
|
36
36
|
const SECURE_FILE_MODE = 0o600;
|
|
37
37
|
/** Directory permission: owner read/write/execute only. */
|
|
38
38
|
const SECURE_DIR_MODE = 0o700;
|
|
39
39
|
/** Environment variable name for the encryption key. */
|
|
40
|
-
const ENV_KEY_NAME = "
|
|
40
|
+
const ENV_KEY_NAME = "DEFENSE_MCP_STATE_KEY";
|
|
41
41
|
// ── Encrypted file format ────────────────────────────────────────────────────
|
|
42
42
|
// Binary layout: [salt (16)] [iv (12)] [authTag (16)] [ciphertext (...)]
|
|
43
43
|
// JSON fallback (unencrypted): plain JSON text
|
|
@@ -45,15 +45,15 @@ const ENV_KEY_NAME = "KALI_DEFENSE_STATE_KEY";
|
|
|
45
45
|
/**
|
|
46
46
|
* Encrypted state storage for sensitive data at rest.
|
|
47
47
|
*
|
|
48
|
-
* Uses AES-256-GCM with PBKDF2-derived keys when `
|
|
48
|
+
* Uses AES-256-GCM with PBKDF2-derived keys when `DEFENSE_MCP_STATE_KEY`
|
|
49
49
|
* is set. Falls back to plaintext JSON when no key is configured.
|
|
50
50
|
*/
|
|
51
51
|
export class SecureStateStore {
|
|
52
52
|
stateDir;
|
|
53
53
|
secret;
|
|
54
54
|
/**
|
|
55
|
-
* @param stateDir - Directory for state files (default: `/tmp/
|
|
56
|
-
* @param secret - Encryption secret. If omitted, reads from `
|
|
55
|
+
* @param stateDir - Directory for state files (default: `/tmp/defense-mcp/state/`)
|
|
56
|
+
* @param secret - Encryption secret. If omitted, reads from `DEFENSE_MCP_STATE_KEY` env var.
|
|
57
57
|
* Pass empty string or omit to use unencrypted fallback.
|
|
58
58
|
*/
|
|
59
59
|
constructor(stateDir, secret) {
|
|
@@ -204,6 +204,6 @@ export class SecureStateStore {
|
|
|
204
204
|
* Default singleton SecureStateStore instance.
|
|
205
205
|
*
|
|
206
206
|
* Uses the default state directory and reads the encryption key from
|
|
207
|
-
* the `
|
|
207
|
+
* the `DEFENSE_MCP_STATE_KEY` environment variable.
|
|
208
208
|
*/
|
|
209
209
|
export const secureState = new SecureStateStore();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"AAkFA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,QAAQ,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AA0FD;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAmNxB"}
|