defense-mcp-server 0.7.1 → 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 +6 -6
- package/LICENSE +1 -1
- package/README.md +10 -10
- 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.js +2 -2
- package/build/core/logger.d.ts +1 -1
- package/build/core/logger.js +2 -2
- 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.js +1 -1
- 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.js +1 -1
- 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/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/secrets.d.ts +1 -1
- package/build/tools/secrets.js +1 -1
- 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
|
@@ -236,13 +236,13 @@ Major security remediation release consolidating 157 tools down to 78 action-bas
|
|
|
236
236
|
|
|
237
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.
|
|
238
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.
|
|
239
|
-
- **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.
|
|
240
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()`.
|
|
241
241
|
|
|
242
242
|
### Test Infrastructure (Phase 2)
|
|
243
243
|
|
|
244
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.
|
|
245
|
-
- **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.
|
|
246
246
|
- **Fix 2.3: Safeguards Real Blockers** — `SafeguardRegistry.checkSafety()` now produces real blocking conditions, not just advisory warnings.
|
|
247
247
|
- **Fix 2.4: spawn-safe.ts Circular Dependency** — Extracted safe spawn helper to break circular dependency between `executor.ts` and `sudo-session.ts`.
|
|
248
248
|
|
|
@@ -343,8 +343,8 @@ Adds a comprehensive pre-flight validation system that automatically checks depe
|
|
|
343
343
|
- `formatStatusMessage()` — compact one-line status for prepending to tool output
|
|
344
344
|
|
|
345
345
|
#### New Environment Variables
|
|
346
|
-
- `
|
|
347
|
-
- `
|
|
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
|
|
348
348
|
|
|
349
349
|
### Changed
|
|
350
350
|
|
|
@@ -485,7 +485,7 @@ Major release expanding the server from 69 tools across 12 categories to 130+ to
|
|
|
485
485
|
- All detection errors are caught gracefully and converted to warnings rather than failures
|
|
486
486
|
|
|
487
487
|
#### `src/core/backup-manager.ts` — BackupManager
|
|
488
|
-
- Manages file backups with manifest tracking under `~/.
|
|
488
|
+
- Manages file backups with manifest tracking under `~/.defense-mcp-backups/`
|
|
489
489
|
- Each backup entry has a UUID, original path, backup path, timestamp, and size
|
|
490
490
|
- `manifest.json` maintains the full backup inventory for list and restore operations
|
|
491
491
|
- `backup(filePath)` — creates timestamped copy and adds to manifest, returns UUID
|
|
@@ -495,7 +495,7 @@ Major release expanding the server from 69 tools across 12 categories to 130+ to
|
|
|
495
495
|
|
|
496
496
|
#### `src/core/rollback.ts` — RollbackManager
|
|
497
497
|
- Singleton that tracks system changes within and across sessions
|
|
498
|
-
- State persisted to `~/.
|
|
498
|
+
- State persisted to `~/.defense-mcp/rollback-state.json`
|
|
499
499
|
- Supports four change types: `file` (backup path), `sysctl` (previous value), `service` (previous state), `firewall` (rollback command)
|
|
500
500
|
- `rollback(operationId)` — reverses all changes for a specific operation in reverse order
|
|
501
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
|
@@ -78,7 +78,7 @@ You don't need to pre-install every security tool. The server automatically dete
|
|
|
78
78
|
|
|
79
79
|
To disable auto-installation entirely, run with:
|
|
80
80
|
```bash
|
|
81
|
-
|
|
81
|
+
DEFENSE_MCP_AUTO_INSTALL=false node build/index.js
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
## Requirements
|
|
@@ -186,18 +186,18 @@ Configuration is via environment variables. All have secure defaults:
|
|
|
186
186
|
|
|
187
187
|
| Variable | Default | Description |
|
|
188
188
|
|----------|---------|-------------|
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
195
|
-
| `
|
|
196
|
-
| `
|
|
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 |
|
|
197
197
|
|
|
198
198
|
To apply changes for real (not just preview), set:
|
|
199
199
|
```bash
|
|
200
|
-
|
|
200
|
+
DEFENSE_MCP_DRY_RUN=false node build/index.js
|
|
201
201
|
```
|
|
202
202
|
|
|
203
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();
|
package/build/core/executor.js
CHANGED
|
@@ -322,7 +322,7 @@ export async function executeCommand(options) {
|
|
|
322
322
|
const timeoutSec = Math.round(timeout / 1000);
|
|
323
323
|
stderr += `\nCommand timed out after ${timeoutSec} seconds. ` +
|
|
324
324
|
`The target may be unreachable or the operation is taking too long. ` +
|
|
325
|
-
`Consider increasing
|
|
325
|
+
`Consider increasing DEFENSE_MCP_COMMAND_TIMEOUT (current: ${timeoutSec}s).`;
|
|
326
326
|
}
|
|
327
327
|
// Detect permission errors from combined output
|
|
328
328
|
const combinedOutput = stdout + "\n" + stderr;
|
|
@@ -346,7 +346,7 @@ export async function executeCommand(options) {
|
|
|
346
346
|
const timeoutSec = Math.round(timeout / 1000);
|
|
347
347
|
const timeoutMsg = `\nCommand timed out after ${timeoutSec} seconds. ` +
|
|
348
348
|
`The target may be unreachable or the operation is taking too long. ` +
|
|
349
|
-
`Consider increasing
|
|
349
|
+
`Consider increasing DEFENSE_MCP_COMMAND_TIMEOUT (current: ${timeoutSec}s).`;
|
|
350
350
|
resolve({
|
|
351
351
|
stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
|
|
352
352
|
stderr: Buffer.concat(stderrChunks).toString("utf-8") + timeoutMsg,
|
package/build/core/logger.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export declare class Logger {
|
|
|
45
45
|
private minLevel;
|
|
46
46
|
constructor(minLevel?: LogLevel);
|
|
47
47
|
/**
|
|
48
|
-
* Read the minimum log level from `
|
|
48
|
+
* Read the minimum log level from `DEFENSE_MCP_LOG_LEVEL` env var.
|
|
49
49
|
* Falls back to `"info"` if unset or invalid.
|
|
50
50
|
*/
|
|
51
51
|
private parseEnvLevel;
|
package/build/core/logger.js
CHANGED
|
@@ -40,11 +40,11 @@ export class Logger {
|
|
|
40
40
|
this.minLevel = minLevel ?? this.parseEnvLevel();
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
* Read the minimum log level from `
|
|
43
|
+
* Read the minimum log level from `DEFENSE_MCP_LOG_LEVEL` env var.
|
|
44
44
|
* Falls back to `"info"` if unset or invalid.
|
|
45
45
|
*/
|
|
46
46
|
parseEnvLevel() {
|
|
47
|
-
const raw = process.env.
|
|
47
|
+
const raw = process.env.DEFENSE_MCP_LOG_LEVEL?.toLowerCase();
|
|
48
48
|
if (raw && raw in LOG_LEVEL_SEVERITY) {
|
|
49
49
|
return raw;
|
|
50
50
|
}
|
|
@@ -25,9 +25,9 @@ export interface RateLimitResult {
|
|
|
25
25
|
* Old entries outside the time window are pruned on each check.
|
|
26
26
|
*
|
|
27
27
|
* Configuration via environment variables:
|
|
28
|
-
* - `
|
|
29
|
-
* - `
|
|
30
|
-
* - `
|
|
28
|
+
* - `DEFENSE_MCP_RATE_LIMIT_PER_TOOL` — Max invocations per tool per window (default: 30)
|
|
29
|
+
* - `DEFENSE_MCP_RATE_LIMIT_GLOBAL` — Max total invocations per window (default: 100)
|
|
30
|
+
* - `DEFENSE_MCP_RATE_LIMIT_WINDOW` — Window size in seconds (default: 60)
|
|
31
31
|
*
|
|
32
32
|
* Set any limit to `0` to disable that particular limit.
|
|
33
33
|
*/
|