mcp-rce-guard 0.1.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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +155 -0
  3. package/dist/audit/log.d.ts +75 -0
  4. package/dist/audit/log.d.ts.map +1 -0
  5. package/dist/audit/log.js +191 -0
  6. package/dist/audit/log.js.map +1 -0
  7. package/dist/canary/tracker.d.ts +38 -0
  8. package/dist/canary/tracker.d.ts.map +1 -0
  9. package/dist/canary/tracker.js +40 -0
  10. package/dist/canary/tracker.js.map +1 -0
  11. package/dist/cli.d.ts +14 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +128 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/cve/replay.d.ts +44 -0
  16. package/dist/cve/replay.d.ts.map +1 -0
  17. package/dist/cve/replay.js +221 -0
  18. package/dist/cve/replay.js.map +1 -0
  19. package/dist/egress/policy.d.ts +27 -0
  20. package/dist/egress/policy.d.ts.map +1 -0
  21. package/dist/egress/policy.js +62 -0
  22. package/dist/egress/policy.js.map +1 -0
  23. package/dist/index.d.ts +27 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +38 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/isolation/cgroups.d.ts +20 -0
  28. package/dist/isolation/cgroups.d.ts.map +1 -0
  29. package/dist/isolation/cgroups.js +33 -0
  30. package/dist/isolation/cgroups.js.map +1 -0
  31. package/dist/isolation/landlock.d.ts +42 -0
  32. package/dist/isolation/landlock.d.ts.map +1 -0
  33. package/dist/isolation/landlock.js +67 -0
  34. package/dist/isolation/landlock.js.map +1 -0
  35. package/dist/isolation/platform.d.ts +27 -0
  36. package/dist/isolation/platform.d.ts.map +1 -0
  37. package/dist/isolation/platform.js +96 -0
  38. package/dist/isolation/platform.js.map +1 -0
  39. package/dist/isolation/sandbox-exec.d.ts +17 -0
  40. package/dist/isolation/sandbox-exec.d.ts.map +1 -0
  41. package/dist/isolation/sandbox-exec.js +58 -0
  42. package/dist/isolation/sandbox-exec.js.map +1 -0
  43. package/dist/normalize.d.ts +32 -0
  44. package/dist/normalize.d.ts.map +1 -0
  45. package/dist/normalize.js +66 -0
  46. package/dist/normalize.js.map +1 -0
  47. package/dist/server.d.ts +15 -0
  48. package/dist/server.d.ts.map +1 -0
  49. package/dist/server.js +152 -0
  50. package/dist/server.js.map +1 -0
  51. package/dist/state.d.ts +34 -0
  52. package/dist/state.d.ts.map +1 -0
  53. package/dist/state.js +104 -0
  54. package/dist/state.js.map +1 -0
  55. package/dist/tools/audit.d.ts +26 -0
  56. package/dist/tools/audit.d.ts.map +1 -0
  57. package/dist/tools/audit.js +97 -0
  58. package/dist/tools/audit.js.map +1 -0
  59. package/dist/tools/getAuditLog.d.ts +34 -0
  60. package/dist/tools/getAuditLog.d.ts.map +1 -0
  61. package/dist/tools/getAuditLog.js +65 -0
  62. package/dist/tools/getAuditLog.js.map +1 -0
  63. package/dist/tools/injectEgress.d.ts +21 -0
  64. package/dist/tools/injectEgress.d.ts.map +1 -0
  65. package/dist/tools/injectEgress.js +49 -0
  66. package/dist/tools/injectEgress.js.map +1 -0
  67. package/dist/tools/register.d.ts +16 -0
  68. package/dist/tools/register.d.ts.map +1 -0
  69. package/dist/tools/register.js +44 -0
  70. package/dist/tools/register.js.map +1 -0
  71. package/dist/tools/scanCve.d.ts +14 -0
  72. package/dist/tools/scanCve.d.ts.map +1 -0
  73. package/dist/tools/scanCve.js +29 -0
  74. package/dist/tools/scanCve.js.map +1 -0
  75. package/dist/tools/trackCanary.d.ts +23 -0
  76. package/dist/tools/trackCanary.d.ts.map +1 -0
  77. package/dist/tools/trackCanary.js +44 -0
  78. package/dist/tools/trackCanary.js.map +1 -0
  79. package/dist/trust-tiers.d.ts +18 -0
  80. package/dist/trust-tiers.d.ts.map +1 -0
  81. package/dist/trust-tiers.js +73 -0
  82. package/dist/trust-tiers.js.map +1 -0
  83. package/dist/types.d.ts +187 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +82 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/version.d.ts +7 -0
  88. package/dist/version.d.ts.map +1 -0
  89. package/dist/version.js +14 -0
  90. package/dist/version.js.map +1 -0
  91. package/package.json +74 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matthias Meyer (StudioMeyer)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # mcp-rce-guard
2
+
3
+ Policy-synthesis + behavioral CVE-replay + canary-tracking library for MCP servers. Foundation Pillar 9.
4
+
5
+ ## v0.1 Scope: Policy-Synthesizer, Not Kernel-Level Sandbox
6
+
7
+ **Be precise about what this is and is not.** v0.1 is a building-block library that synthesizes isolation **policy descriptors** (landlock JSON profiles, sandbox-exec `.sb` scheme files, cgroups-v2 spec maps) and provides **behavioral predicates** that scan subprocess commands for known RCE-vulnerability shapes. It does **not** apply those policies to a running process. The host spawning the subprocess is responsible for translating a descriptor into the platform-specific syscall (Linux landlock, macOS sandbox-exec, cgroups-v2 fs write).
8
+
9
+ **Native enforcement** (NAPI-RS landlock binding, sandbox-exec execa wrap, cgroups-v2 file writes with cleanup-on-exit, cross-platform integration tests) is the **v0.2 tranche** and is not bundled with v0.1. Layered defense relies on the host wiring policy emission to actual enforcement; this library does the first half cleanly.
10
+
11
+ Use this library if you want:
12
+ - A typed, validated way to describe what an MCP subprocess is allowed to read, write, spawn, and talk to.
13
+ - A reproducible scanner for known RCE-vulnerability classes in subprocess commands (MCP-SDK-RCE-2026-04-22, CVE-2026-27124, Nginx-MCP RCE 9.8) plus 5 shell-injection + 3 fullwidth-unicode payload patterns from the simulate_attacker_input corpus.
14
+ - An append-only NDJSON audit log of every isolation decision. Verified tamper-evident signing (Acra-pattern key derivation + rotation + integrated verifier) is on the v0.2 roadmap; v0.1 ships the log unsigned and treats signing as a v0.2 deliverable.
15
+
16
+ Do **not** use v0.1 if you need a sandbox that actually contains a hostile subprocess at the kernel boundary. For that, the v0.1 descriptor needs to be paired with an enforcement helper. v0.2 ships that helper.
17
+
18
+ ## What it does (v0.1)
19
+
20
+ - **Process isolation policy synthesis** — emits landlock (Linux >=5.13) policy descriptors, sandbox-exec (macOS) Scheme profiles, cgroups-v2 specs (memory.max, pids.max, cpu.max). Descriptors only; no syscalls are made.
21
+ - **Network egress allowlist** — default-deny policy with wildcard / exact / suffix / port:* matching. Descriptors only; no nftables / packet-filter integration.
22
+ - **CVE replay suite** — behavioral predicates for known MCP-server RCE vectors. Not exploit payloads — predicates that scan a target command for the vulnerable shape.
23
+ - **Cross-server canary tokens** — issue tokens, scan downstream stdout / fs-write / network-egress streams for leaks (MCPHunt arXiv 2604.27819 pattern).
24
+ - **NDJSON append-only audit log** — every tool call appended at `$MCP_RCE_GUARD_HOME/audit.log`. 100MB rotation with max 10 backups. v0.1 ships unsigned (no in-process verifier); v0.2 adds Acra-pattern HMAC chain with key derivation, rotation safety and an integrated verifier.
25
+ - **NFKC + zero-width strip + Bidi-block** normalization shared with Pillar 8 (mcp-stdio-shellguard).
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ npm install -g mcp-rce-guard
31
+ ```
32
+
33
+ Or run via npx:
34
+
35
+ ```bash
36
+ npx -y mcp-rce-guard serve
37
+ ```
38
+
39
+ ## Tools (MCP, Spec 2025-06-18)
40
+
41
+ | Tool | Purpose | readOnly | destructive |
42
+ |------|---------|----------|-------------|
43
+ | `register_subprocess` | Register a child MCP server with isolation profile, get back a handle + fingerprint + policy descriptor | yes | no |
44
+ | `audit_subprocess` | Verify requested args match registered allowlist (post-NFKC, smell-test for invisibles) | yes | no |
45
+ | `scan_cve_replay` | Run behavioral predicates against a target server command | yes | no |
46
+ | `track_canary` | Issue a canary token + scan downstream servers for leaks | yes | no |
47
+ | `inject_egress_policy` | Emit network-egress allowlist descriptor for a registered subprocess (v0.1 descriptor-only) | yes | no |
48
+ | `get_audit_log` | Read NDJSON audit log entries with filters | yes | no |
49
+
50
+ > **v0.1 Honesty Note:** all six tools are `readOnlyHint=true, destructiveHint=false` in v0.1 because they emit policy descriptors + append to the audit log but do not modify subprocess state. v0.2 will flip `inject_egress_policy` to `destructiveHint=true` when native enforcement is wired in.
51
+
52
+ ## CLI
53
+
54
+ ```bash
55
+ mcp-rce-guard serve # start MCP server on stdio
56
+ mcp-rce-guard platform # detect isolation backend (landlock/sandbox-exec/unsupported)
57
+ mcp-rce-guard scan-cve <cmd> # one-shot CVE replay against a command
58
+ mcp-rce-guard audit-log # tail the audit log
59
+ mcp-rce-guard policy <profile.json> # synthesize landlock+cgroups+sandbox-exec from JSON
60
+ ```
61
+
62
+ ## Compatibility matrix
63
+
64
+ | Platform | Isolation backend | Network egress | cgroups |
65
+ |----------|-------------------|----------------|---------|
66
+ | Linux >= 5.13 | landlock | nftables hook (out-of-band) | cgroups-v2 |
67
+ | Linux < 5.13 | unsupported | unsupported | unsupported |
68
+ | macOS 11+ | sandbox-exec (.sb) | sandbox-exec network rules | n/a |
69
+ | Windows | unsupported (planned: AppContainer) | n/a | n/a |
70
+
71
+ ## Layer architecture (v0.1)
72
+
73
+ ```
74
+ Pillar 1 (mcp-protocol-conformance) — protocol input shape
75
+
76
+ Pillar 8 (mcp-stdio-shellguard) — argv allowlist + invisible-codepoint detection
77
+
78
+ Pillar 9 (mcp-rce-guard, this lib) — policy synthesis + CVE-replay scan + canary
79
+
80
+ Host spawner (caller responsibility) — applies the policy descriptor via real syscalls
81
+ ```
82
+
83
+ In v0.2 the bottom box collapses into Pillar 9 (NAPI-RS landlock binding, sandbox-exec exec wrap, cgroups-v2 fs writes with cleanup). Until then, the host has to bridge the descriptor to the platform.
84
+
85
+ ## Trust tiers
86
+
87
+ | Tier | mem | pids | egress | use |
88
+ |------|-----|------|--------|-----|
89
+ | `LOW` | 256MB | 32 | none | untrusted MCP from registry |
90
+ | `MEDIUM` | 512MB | 64 | api-only | known vendor with limited scope |
91
+ | `HIGH` | 1024MB | 128 | broad | first-party MCP with reviewed source |
92
+ | `CRITICAL` | 2048MB | 256 | unrestricted | local OS-integrated MCP, you own the source |
93
+
94
+ ## Audit log location
95
+
96
+ ```
97
+ $MCP_RCE_GUARD_HOME/audit.log # default: ~/.mcp-rce-guard/audit.log
98
+ ```
99
+
100
+ Entries are written as one JSON document per line (NDJSON) and read back via
101
+ `JSON.parse` per line, so arbitrary characters inside `args` strings (tabs,
102
+ quotes, embedded escape sequences) round-trip safely. Rotation happens at
103
+ 100MB; up to 10 backups (`audit.log.1` .. `audit.log.10`) are kept.
104
+
105
+ v0.1 does **not** sign entries. The previous `MCP_RCE_GUARD_SIGNING_KEY`
106
+ HMAC-SHA256 path was removed pre-publish: there was no in-process verifier,
107
+ no key-length validation, and no rotation strategy, which would have been
108
+ security theatre. v0.2 ships a verified Acra-pattern chain (`KDF(master) →
109
+ per-entry HMAC`, key rotation, an integrated `verify_audit_log` tool).
110
+
111
+ ## Notes
112
+
113
+ - v0.1 emits **policy descriptors**. Actual landlock syscall application is the responsibility of the spawning helper (separation-of-concerns: policy synthesis is portable, syscall is platform-specific). A native bindings wrapper is planned for v0.2.
114
+ - CVE fixtures are **behavioral predicates**, not runnable exploits. They check: "does the target command match the shape known to be exploitable?" Not "can we trigger the exploit?"
115
+ - Canary tokens use crypto-random 64-hex bodies inside `__MCP_CANARY_<hex>__` markers. Pattern uniqueness is statistical, not crypto-guaranteed against an adversary that controls the generator.
116
+
117
+ ## Known Issues v0.1
118
+
119
+ These are real but accepted limitations of the v0.1 line. They are tracked in
120
+ the v0.2 roadmap below; if any of them blocks your use case, pin to a future
121
+ v0.2.x release once it ships.
122
+
123
+ - **Audit-log rotation has a TOCTOU window** (`src/audit/log.ts`
124
+ `rotateAuditLog`). The size check and the rename are not atomic. In
125
+ multi-process / high-concurrency setups two appenders may both observe
126
+ "needs rotation" and both attempt the rename; the loser's append lands in
127
+ the freshly-created empty active log. Workaround: serialize writes or run
128
+ one writer per process. v0.2 will gate rotation behind `proper-lockfile`.
129
+ - **In-memory state lost on restart** (`src/state.ts`). Registered
130
+ subprocesses and canary chains live in process memory. A process restart
131
+ empties the registry; the operator has to re-register. v0.2 plans a
132
+ SQLite-backed store as an opt-in persistence layer.
133
+ - **`mcp-protocol-validator` CI step is not a hard gate**
134
+ (`.github/workflows/ci.yml`). The validator runs with
135
+ `continue-on-error: true` because the upstream tool is still stabilising;
136
+ failures surface as CI annotations but do not block. v0.2 promotes it to a
137
+ hard gate once upstream is stable.
138
+ - **Audit log is unsigned in v0.1**. See "Audit log location" above. v0.2
139
+ adds a verified Acra-pattern signed chain.
140
+
141
+ ## v0.2 Roadmap (parked, no commit date)
142
+
143
+ - pnpm-workspace mit `mcp-rce-guard` + `mcp-rce-demo` + `mcp-rce-fixtures` (Marketplace-Distribution-Hygiene: CVE-Fixtures separate distribution).
144
+ - NAPI-RS Landlock binding fuer Linux (kernel >=5.13). Plain `child_process.spawn` mit prctl + LANDLOCK_CREATE_RULESET ist nicht testbar ohne C-Bridge.
145
+ - macOS sandbox-exec execa wrap mit profile-file lifecycle (deny-network triggert connection-refused, deny-fs-read triggert EACCES).
146
+ - cgroups-v2 fs.writeFile mit Permission-Checks + cleanup-on-exit + signal handlers.
147
+ - Integration tests `tests/integration/linux-landlock.test.ts` + `tests/integration/macos-sandbox-exec.test.ts`.
148
+ - Reference server `mcp-rce-demo` mit 6 Tools die jede Capability live demonstrieren (read_isolated_file, attempt_egress_blocked, spawn_subprocess_audited, replay_cve_demo, inject_canary_demo, get_demo_audit).
149
+ - Latency test "subprocess-Spawn p95 <200ms" auf ubuntu-latest GitHub Actions runner.
150
+ - Sigstore Trusted Publishing OIDC fuer alle 3 npm-Packages.
151
+ - Verified Acra-pattern audit-log chain: KDF master-key → per-entry HMAC, key rotation with overlap window, integrated `verify_audit_log` tool. Replaces the v0.1 HMAC-SHA256 prototype that was removed pre-publish for lacking a verifier.
152
+
153
+ ## License
154
+
155
+ MIT — Copyright (c) 2026 Matthias Meyer (StudioMeyer)
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Append-only NDJSON audit log.
3
+ *
4
+ * Path: ${MCP_RCE_GUARD_HOME:-~/.mcp-rce-guard}/audit.log
5
+ *
6
+ * Each line is a JSON-serialized AuditLogEntry. The log is append-only with
7
+ * size-based rotation (Reviewer S1024 F6): when the active log exceeds
8
+ * `MCP_RCE_GUARD_AUDIT_MAX_BYTES` (default 100MB), it is atomically renamed
9
+ * to `audit.log.1`, the previous .1 becomes .2, etc., up to .10. Anything
10
+ * beyond .10 is dropped to bound disk usage.
11
+ *
12
+ * Pre-Publish-Audit (2026-05-13 F1/F3/F5):
13
+ * - HMAC-SHA256 signing path removed: the v0.1 implementation lacked a
14
+ * verifier, key-validation and rotation-safety, making it security
15
+ * theatre per Acra-pattern (industry baseline for HMAC audit-log chains).
16
+ * v0.2 will reintroduce a verified Acra-style signed chain.
17
+ * - NDJSON reader now uses `JSON.parse(line.trim())` per line; the previous
18
+ * tab-splitting scheme silently dropped entries whose arg strings
19
+ * contained a literal tab character.
20
+ */
21
+ import type { AuditLogEntry } from "../types.js";
22
+ export declare function auditLogPath(): string;
23
+ /**
24
+ * Rotate the active log: rename audit.log → audit.log.1 (shifting existing
25
+ * .1 → .2 etc., up to .MAX_ROTATED_BACKUPS). Anything beyond .10 is unlinked.
26
+ * Atomic via fs.rename, which is atomic on the same filesystem on POSIX.
27
+ *
28
+ * Known Issue v0.1 (Pre-Publish-Audit F2): TOCTOU race window between the
29
+ * size-check and the rename. In multi-process / high-concurrency setups, two
30
+ * appenders may both observe "needs rotation" and both attempt the rename;
31
+ * the loser's append lands in the freshly-created empty active log. v0.2
32
+ * will gate rotation behind `proper-lockfile` or an equivalent advisory
33
+ * lockfile. v0.1 callers should serialize writes or accept the race.
34
+ */
35
+ export declare function rotateAuditLog(): Promise<{
36
+ rotated: boolean;
37
+ reason?: string;
38
+ }>;
39
+ /**
40
+ * Append a single audit-log entry. Idempotent against duplicate calls — every
41
+ * call writes a distinct line because `ts` is auto-stamped if missing.
42
+ *
43
+ * Triggers rotation BEFORE writing if the active log already exceeds the
44
+ * configured cap. This is a best-effort guard; under heavy concurrency the
45
+ * log may briefly exceed the cap by one batch (acceptable for audit
46
+ * semantics).
47
+ */
48
+ export declare function appendAudit(entry: Omit<AuditLogEntry, "ts"> & {
49
+ ts?: string;
50
+ }): Promise<void>;
51
+ /**
52
+ * Read entries with optional filters.
53
+ *
54
+ * Pre-Publish-Audit F3: each line is parsed as a single JSON document. The
55
+ * earlier implementation split on the last tab character (legacy HMAC suffix
56
+ * carve-out); arg strings containing a literal tab were silently truncated
57
+ * and the surviving prefix failed JSON.parse, dropping the entry. The
58
+ * NDJSON-standard read path used here is robust to any byte content the
59
+ * JSON encoder produced.
60
+ */
61
+ export declare function readAudit(filter?: {
62
+ subprocessHandle?: string;
63
+ since?: string;
64
+ limit?: number;
65
+ }): Promise<AuditLogEntry[]>;
66
+ /**
67
+ * Test helper: clear the log file. NOT a public API — imported directly
68
+ * from this module by tests; intentionally absent from `src/index.ts`
69
+ * re-exports so external consumers cannot accidentally drop their
70
+ * audit trail (Pre-Publish-Audit F9).
71
+ *
72
+ * @internal
73
+ */
74
+ export declare function clearAuditLog(): Promise<void>;
75
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/audit/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAajD,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAiBD;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBrF;AAYD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,MAAM,CAAC,EAAE;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CA4B3B;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAYnD"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Append-only NDJSON audit log.
3
+ *
4
+ * Path: ${MCP_RCE_GUARD_HOME:-~/.mcp-rce-guard}/audit.log
5
+ *
6
+ * Each line is a JSON-serialized AuditLogEntry. The log is append-only with
7
+ * size-based rotation (Reviewer S1024 F6): when the active log exceeds
8
+ * `MCP_RCE_GUARD_AUDIT_MAX_BYTES` (default 100MB), it is atomically renamed
9
+ * to `audit.log.1`, the previous .1 becomes .2, etc., up to .10. Anything
10
+ * beyond .10 is dropped to bound disk usage.
11
+ *
12
+ * Pre-Publish-Audit (2026-05-13 F1/F3/F5):
13
+ * - HMAC-SHA256 signing path removed: the v0.1 implementation lacked a
14
+ * verifier, key-validation and rotation-safety, making it security
15
+ * theatre per Acra-pattern (industry baseline for HMAC audit-log chains).
16
+ * v0.2 will reintroduce a verified Acra-style signed chain.
17
+ * - NDJSON reader now uses `JSON.parse(line.trim())` per line; the previous
18
+ * tab-splitting scheme silently dropped entries whose arg strings
19
+ * contained a literal tab character.
20
+ */
21
+ import { promises as fs } from "node:fs";
22
+ import { existsSync, mkdirSync, statSync } from "node:fs";
23
+ import { homedir } from "node:os";
24
+ import { join, dirname } from "node:path";
25
+ /**
26
+ * Reviewer S1024 F6: cap on active log size before rotation. Default 100MB.
27
+ * Configurable via env so ops can tune for high-volume tenants.
28
+ */
29
+ const DEFAULT_MAX_BYTES = 100 * 1024 * 1024;
30
+ const MAX_ROTATED_BACKUPS = 10;
31
+ function homeDir() {
32
+ return process.env["MCP_RCE_GUARD_HOME"] ?? join(homedir(), ".mcp-rce-guard");
33
+ }
34
+ export function auditLogPath() {
35
+ return join(homeDir(), "audit.log");
36
+ }
37
+ function maxBytes() {
38
+ const raw = process.env["MCP_RCE_GUARD_AUDIT_MAX_BYTES"];
39
+ if (!raw)
40
+ return DEFAULT_MAX_BYTES;
41
+ const parsed = Number.parseInt(raw, 10);
42
+ if (!Number.isFinite(parsed) || parsed <= 0)
43
+ return DEFAULT_MAX_BYTES;
44
+ return parsed;
45
+ }
46
+ function ensureDir(path) {
47
+ const dir = dirname(path);
48
+ if (!existsSync(dir)) {
49
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
50
+ }
51
+ }
52
+ /**
53
+ * Rotate the active log: rename audit.log → audit.log.1 (shifting existing
54
+ * .1 → .2 etc., up to .MAX_ROTATED_BACKUPS). Anything beyond .10 is unlinked.
55
+ * Atomic via fs.rename, which is atomic on the same filesystem on POSIX.
56
+ *
57
+ * Known Issue v0.1 (Pre-Publish-Audit F2): TOCTOU race window between the
58
+ * size-check and the rename. In multi-process / high-concurrency setups, two
59
+ * appenders may both observe "needs rotation" and both attempt the rename;
60
+ * the loser's append lands in the freshly-created empty active log. v0.2
61
+ * will gate rotation behind `proper-lockfile` or an equivalent advisory
62
+ * lockfile. v0.1 callers should serialize writes or accept the race.
63
+ */
64
+ export async function rotateAuditLog() {
65
+ const active = auditLogPath();
66
+ if (!existsSync(active)) {
67
+ return { rotated: false, reason: "no active log" };
68
+ }
69
+ // Shift backups: .9 → .10, .8 → .9, ..., .1 → .2
70
+ for (let i = MAX_ROTATED_BACKUPS; i >= 2; i--) {
71
+ const from = `${active}.${i - 1}`;
72
+ const to = `${active}.${i}`;
73
+ if (existsSync(from)) {
74
+ // If destination exists (overflow at .10), drop it first.
75
+ if (existsSync(to)) {
76
+ await fs.unlink(to);
77
+ }
78
+ await fs.rename(from, to);
79
+ }
80
+ }
81
+ // Move active → .1
82
+ const dotOne = `${active}.1`;
83
+ if (existsSync(dotOne)) {
84
+ await fs.unlink(dotOne);
85
+ }
86
+ await fs.rename(active, dotOne);
87
+ return { rotated: true };
88
+ }
89
+ function shouldRotate(path) {
90
+ if (!existsSync(path))
91
+ return false;
92
+ try {
93
+ const st = statSync(path);
94
+ return st.size >= maxBytes();
95
+ }
96
+ catch {
97
+ return false;
98
+ }
99
+ }
100
+ /**
101
+ * Append a single audit-log entry. Idempotent against duplicate calls — every
102
+ * call writes a distinct line because `ts` is auto-stamped if missing.
103
+ *
104
+ * Triggers rotation BEFORE writing if the active log already exceeds the
105
+ * configured cap. This is a best-effort guard; under heavy concurrency the
106
+ * log may briefly exceed the cap by one batch (acceptable for audit
107
+ * semantics).
108
+ */
109
+ export async function appendAudit(entry) {
110
+ const finalEntry = {
111
+ ts: entry.ts ?? new Date().toISOString(),
112
+ subprocessHandle: entry.subprocessHandle,
113
+ action: entry.action,
114
+ verdict: entry.verdict,
115
+ ...(entry.serverId !== undefined ? { serverId: entry.serverId } : {}),
116
+ ...(entry.reason !== undefined ? { reason: entry.reason } : {}),
117
+ ...(entry.meta !== undefined ? { meta: entry.meta } : {})
118
+ };
119
+ const path = auditLogPath();
120
+ ensureDir(path);
121
+ if (shouldRotate(path)) {
122
+ await rotateAuditLog();
123
+ }
124
+ // JSON.stringify never emits a literal newline inside the string (all
125
+ // control chars are escaped). One entry == one NDJSON line.
126
+ const line = JSON.stringify(finalEntry);
127
+ await fs.appendFile(path, line + "\n", { mode: 0o600 });
128
+ }
129
+ /**
130
+ * Read entries with optional filters.
131
+ *
132
+ * Pre-Publish-Audit F3: each line is parsed as a single JSON document. The
133
+ * earlier implementation split on the last tab character (legacy HMAC suffix
134
+ * carve-out); arg strings containing a literal tab were silently truncated
135
+ * and the surviving prefix failed JSON.parse, dropping the entry. The
136
+ * NDJSON-standard read path used here is robust to any byte content the
137
+ * JSON encoder produced.
138
+ */
139
+ export async function readAudit(filter) {
140
+ const path = auditLogPath();
141
+ if (!existsSync(path))
142
+ return [];
143
+ const raw = await fs.readFile(path, "utf8");
144
+ // Splitting on \n is safe: JSON.stringify escapes embedded newlines as \n
145
+ // (literal two-character sequence) so a real newline only appears at the
146
+ // entry boundary written by appendAudit.
147
+ const lines = raw.split("\n").filter((l) => l.length > 0);
148
+ const entries = [];
149
+ for (const rawLine of lines) {
150
+ try {
151
+ const parsed = JSON.parse(rawLine.trim());
152
+ if (filter?.subprocessHandle && parsed.subprocessHandle !== filter.subprocessHandle) {
153
+ continue;
154
+ }
155
+ if (filter?.since && parsed.ts < filter.since) {
156
+ continue;
157
+ }
158
+ entries.push(parsed);
159
+ }
160
+ catch {
161
+ // Skip malformed lines; production: add a counter + WARN log.
162
+ continue;
163
+ }
164
+ }
165
+ if (filter?.limit && entries.length > filter.limit) {
166
+ return entries.slice(-filter.limit);
167
+ }
168
+ return entries;
169
+ }
170
+ /**
171
+ * Test helper: clear the log file. NOT a public API — imported directly
172
+ * from this module by tests; intentionally absent from `src/index.ts`
173
+ * re-exports so external consumers cannot accidentally drop their
174
+ * audit trail (Pre-Publish-Audit F9).
175
+ *
176
+ * @internal
177
+ */
178
+ export async function clearAuditLog() {
179
+ const path = auditLogPath();
180
+ if (existsSync(path)) {
181
+ await fs.unlink(path);
182
+ }
183
+ // Also clear any rotated backups so test runs start clean.
184
+ for (let i = 1; i <= MAX_ROTATED_BACKUPS; i++) {
185
+ const backup = `${path}.${i}`;
186
+ if (existsSync(backup)) {
187
+ await fs.unlink(backup);
188
+ }
189
+ }
190
+ }
191
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/audit/log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Canary token tracking for cross-server credential leak detection.
3
+ *
4
+ * Pattern provenance: arXiv 2604.27819 (MCPHunt, April 2026) — taint tracking
5
+ * via canary-token injection across MCP server boundaries. If a token leaves
6
+ * the chain via stdout/network/fs, the controller flags the leak channel.
7
+ *
8
+ * v0.1 ist scanner-only: detect_leaks scant a corpus of textual outputs for
9
+ * the canary token. The actual injection happens at the calling MCP server's
10
+ * tool boundary via track_canary which returns the token + downstream IDs.
11
+ */
12
+ export type LeakChannel = "stdout" | "network-egress" | "fs-write";
13
+ export interface LeakLocation {
14
+ serverId: string;
15
+ channel: LeakChannel;
16
+ }
17
+ export interface CorpusEntry {
18
+ serverId: string;
19
+ channel: LeakChannel;
20
+ content: string;
21
+ }
22
+ /**
23
+ * Build a canary token + pattern. Caller may supply a fixed pattern (for
24
+ * tests) or accept the high-entropy default.
25
+ */
26
+ export declare function makeCanary(pattern?: string): {
27
+ token: string;
28
+ pattern: string;
29
+ };
30
+ /**
31
+ * Scan a corpus for canary leaks. Returns one LeakLocation per matching entry.
32
+ *
33
+ * False-positive note: a tool that legitimately echoes a canary in its own
34
+ * structured output would be flagged. Mitigation: callers should redact the
35
+ * token from logs they emit, or pass a unique pattern per chain.
36
+ */
37
+ export declare function detectLeaks(corpus: readonly CorpusEntry[], pattern: string): LeakLocation[];
38
+ //# sourceMappingURL=tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/canary/tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,gBAAgB,GAAG,UAAU,CAAC;AAEnE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAM/E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,OAAO,EAAE,MAAM,GACd,YAAY,EAAE,CAQhB"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Canary token tracking for cross-server credential leak detection.
3
+ *
4
+ * Pattern provenance: arXiv 2604.27819 (MCPHunt, April 2026) — taint tracking
5
+ * via canary-token injection across MCP server boundaries. If a token leaves
6
+ * the chain via stdout/network/fs, the controller flags the leak channel.
7
+ *
8
+ * v0.1 ist scanner-only: detect_leaks scant a corpus of textual outputs for
9
+ * the canary token. The actual injection happens at the calling MCP server's
10
+ * tool boundary via track_canary which returns the token + downstream IDs.
11
+ */
12
+ import { generateCanaryToken } from "../state.js";
13
+ /**
14
+ * Build a canary token + pattern. Caller may supply a fixed pattern (for
15
+ * tests) or accept the high-entropy default.
16
+ */
17
+ export function makeCanary(pattern) {
18
+ const token = generateCanaryToken();
19
+ return {
20
+ token,
21
+ pattern: pattern ?? token
22
+ };
23
+ }
24
+ /**
25
+ * Scan a corpus for canary leaks. Returns one LeakLocation per matching entry.
26
+ *
27
+ * False-positive note: a tool that legitimately echoes a canary in its own
28
+ * structured output would be flagged. Mitigation: callers should redact the
29
+ * token from logs they emit, or pass a unique pattern per chain.
30
+ */
31
+ export function detectLeaks(corpus, pattern) {
32
+ const out = [];
33
+ for (const entry of corpus) {
34
+ if (entry.content.includes(pattern)) {
35
+ out.push({ serverId: entry.serverId, channel: entry.channel });
36
+ }
37
+ }
38
+ return out;
39
+ }
40
+ //# sourceMappingURL=tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/canary/tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAelD;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;IACpC,OAAO;QACL,KAAK;QACL,OAAO,EAAE,OAAO,IAAI,KAAK;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,MAA8B,EAC9B,OAAe;IAEf,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACpC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * mcp-rce-guard CLI.
3
+ *
4
+ * Subcommands:
5
+ * serve — run the stdio MCP server (same as mcp-rce-guard-server bin)
6
+ * platform — print detected isolation backend + capabilities
7
+ * scan-cve <command...> — run CVE replay fixtures against a candidate command
8
+ * audit-log [--since=..] — print recent audit-log entries
9
+ * policy <profile.json> — emit landlock + sandbox-exec + cgroups specs from a profile
10
+ */
11
+ import { Command } from "commander";
12
+ declare const program: Command;
13
+ export { program };
14
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA8G9B,OAAO,EAAE,OAAO,EAAE,CAAC"}