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.
- package/LICENSE +21 -0
- package/README.md +155 -0
- package/dist/audit/log.d.ts +75 -0
- package/dist/audit/log.d.ts.map +1 -0
- package/dist/audit/log.js +191 -0
- package/dist/audit/log.js.map +1 -0
- package/dist/canary/tracker.d.ts +38 -0
- package/dist/canary/tracker.d.ts.map +1 -0
- package/dist/canary/tracker.js +40 -0
- package/dist/canary/tracker.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +128 -0
- package/dist/cli.js.map +1 -0
- package/dist/cve/replay.d.ts +44 -0
- package/dist/cve/replay.d.ts.map +1 -0
- package/dist/cve/replay.js +221 -0
- package/dist/cve/replay.js.map +1 -0
- package/dist/egress/policy.d.ts +27 -0
- package/dist/egress/policy.d.ts.map +1 -0
- package/dist/egress/policy.js +62 -0
- package/dist/egress/policy.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/isolation/cgroups.d.ts +20 -0
- package/dist/isolation/cgroups.d.ts.map +1 -0
- package/dist/isolation/cgroups.js +33 -0
- package/dist/isolation/cgroups.js.map +1 -0
- package/dist/isolation/landlock.d.ts +42 -0
- package/dist/isolation/landlock.d.ts.map +1 -0
- package/dist/isolation/landlock.js +67 -0
- package/dist/isolation/landlock.js.map +1 -0
- package/dist/isolation/platform.d.ts +27 -0
- package/dist/isolation/platform.d.ts.map +1 -0
- package/dist/isolation/platform.js +96 -0
- package/dist/isolation/platform.js.map +1 -0
- package/dist/isolation/sandbox-exec.d.ts +17 -0
- package/dist/isolation/sandbox-exec.d.ts.map +1 -0
- package/dist/isolation/sandbox-exec.js +58 -0
- package/dist/isolation/sandbox-exec.js.map +1 -0
- package/dist/normalize.d.ts +32 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +66 -0
- package/dist/normalize.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +152 -0
- package/dist/server.js.map +1 -0
- package/dist/state.d.ts +34 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +104 -0
- package/dist/state.js.map +1 -0
- package/dist/tools/audit.d.ts +26 -0
- package/dist/tools/audit.d.ts.map +1 -0
- package/dist/tools/audit.js +97 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/getAuditLog.d.ts +34 -0
- package/dist/tools/getAuditLog.d.ts.map +1 -0
- package/dist/tools/getAuditLog.js +65 -0
- package/dist/tools/getAuditLog.js.map +1 -0
- package/dist/tools/injectEgress.d.ts +21 -0
- package/dist/tools/injectEgress.d.ts.map +1 -0
- package/dist/tools/injectEgress.js +49 -0
- package/dist/tools/injectEgress.js.map +1 -0
- package/dist/tools/register.d.ts +16 -0
- package/dist/tools/register.d.ts.map +1 -0
- package/dist/tools/register.js +44 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/tools/scanCve.d.ts +14 -0
- package/dist/tools/scanCve.d.ts.map +1 -0
- package/dist/tools/scanCve.js +29 -0
- package/dist/tools/scanCve.js.map +1 -0
- package/dist/tools/trackCanary.d.ts +23 -0
- package/dist/tools/trackCanary.d.ts.map +1 -0
- package/dist/tools/trackCanary.js +44 -0
- package/dist/tools/trackCanary.js.map +1 -0
- package/dist/trust-tiers.d.ts +18 -0
- package/dist/trust-tiers.d.ts.map +1 -0
- package/dist/trust-tiers.js +73 -0
- package/dist/trust-tiers.js.map +1 -0
- package/dist/types.d.ts +187 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +82 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +14 -0
- package/dist/version.js.map +1 -0
- package/package.json +74 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* mcp-rce-guard CLI.
|
|
4
|
+
*
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* serve — run the stdio MCP server (same as mcp-rce-guard-server bin)
|
|
7
|
+
* platform — print detected isolation backend + capabilities
|
|
8
|
+
* scan-cve <command...> — run CVE replay fixtures against a candidate command
|
|
9
|
+
* audit-log [--since=..] — print recent audit-log entries
|
|
10
|
+
* policy <profile.json> — emit landlock + sandbox-exec + cgroups specs from a profile
|
|
11
|
+
*/
|
|
12
|
+
import { Command } from "commander";
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
14
|
+
import { detectPlatform } from "./isolation/platform.js";
|
|
15
|
+
import { runReplay } from "./cve/replay.js";
|
|
16
|
+
import { readAudit, rotateAuditLog, auditLogPath } from "./audit/log.js";
|
|
17
|
+
import { buildLandlockPolicy } from "./isolation/landlock.js";
|
|
18
|
+
import { buildSandboxProfile } from "./isolation/sandbox-exec.js";
|
|
19
|
+
import { buildCgroupSpec } from "./isolation/cgroups.js";
|
|
20
|
+
import { IsolationProfileSchema } from "./types.js";
|
|
21
|
+
import { resolveProfile } from "./trust-tiers.js";
|
|
22
|
+
import { NAME, VERSION } from "./version.js";
|
|
23
|
+
import { main as serverMain } from "./server.js";
|
|
24
|
+
const program = new Command();
|
|
25
|
+
program
|
|
26
|
+
.name(NAME)
|
|
27
|
+
.description("Layer-3 RCE defense for MCP servers")
|
|
28
|
+
.version(VERSION);
|
|
29
|
+
program
|
|
30
|
+
.command("serve")
|
|
31
|
+
.description("Run the stdio MCP server")
|
|
32
|
+
.action(async () => {
|
|
33
|
+
await serverMain();
|
|
34
|
+
});
|
|
35
|
+
program
|
|
36
|
+
.command("platform")
|
|
37
|
+
.description("Print detected isolation backend + capabilities")
|
|
38
|
+
.action(() => {
|
|
39
|
+
const info = detectPlatform();
|
|
40
|
+
process.stdout.write(JSON.stringify(info, null, 2) + "\n");
|
|
41
|
+
});
|
|
42
|
+
program
|
|
43
|
+
.command("scan-cve")
|
|
44
|
+
.description("Run CVE replay fixtures against a candidate command")
|
|
45
|
+
.argument("<command...>", "command tokens (joined with spaces)")
|
|
46
|
+
.option("--cve <ids...>", "CVE IDs to run (default: all)")
|
|
47
|
+
.option("--timeout <ms>", "timeout in milliseconds", "30000")
|
|
48
|
+
.action((cmdTokens, opts) => {
|
|
49
|
+
const command = cmdTokens.join(" ");
|
|
50
|
+
const cveSet = opts.cve;
|
|
51
|
+
const timeoutMs = parseInt(opts.timeout, 10) || 30_000;
|
|
52
|
+
const result = runReplay(command, cveSet, timeoutMs);
|
|
53
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
54
|
+
process.exit(result.overall === "pass" ? 0 : 2);
|
|
55
|
+
});
|
|
56
|
+
program
|
|
57
|
+
.command("audit-log")
|
|
58
|
+
.description("Print recent audit-log entries")
|
|
59
|
+
.option("--since <iso>", "only entries since this ISO timestamp")
|
|
60
|
+
.option("--handle <h>", "filter by subprocess handle")
|
|
61
|
+
.option("--limit <n>", "max entries", "100")
|
|
62
|
+
.action(async (opts) => {
|
|
63
|
+
const filter = {
|
|
64
|
+
limit: parseInt(opts.limit, 10) || 100
|
|
65
|
+
};
|
|
66
|
+
if (opts.since)
|
|
67
|
+
filter.since = opts.since;
|
|
68
|
+
if (opts.handle)
|
|
69
|
+
filter.subprocessHandle = opts.handle;
|
|
70
|
+
const entries = await readAudit(filter);
|
|
71
|
+
for (const e of entries) {
|
|
72
|
+
process.stdout.write(JSON.stringify(e) + "\n");
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
program
|
|
76
|
+
.command("cleanup")
|
|
77
|
+
.description("Force-rotate the audit log (audit.log → audit.log.1, shifting backups)")
|
|
78
|
+
.action(async () => {
|
|
79
|
+
const result = await rotateAuditLog();
|
|
80
|
+
process.stdout.write(JSON.stringify({ ...result, path: auditLogPath() }, null, 2) + "\n");
|
|
81
|
+
});
|
|
82
|
+
program
|
|
83
|
+
.command("policy")
|
|
84
|
+
.description("Emit isolation specs from a profile JSON file")
|
|
85
|
+
.argument("<file>", "path to profile JSON")
|
|
86
|
+
.option("--tier <tier>", "trust tier base (LOW|MEDIUM|HIGH|CRITICAL)", "MEDIUM")
|
|
87
|
+
.option("--cgroup-name <name>", "cgroup name for cgroups spec", "mcp-rce-guard-default")
|
|
88
|
+
.action((file, opts) => {
|
|
89
|
+
const raw = readFileSync(file, "utf8");
|
|
90
|
+
const overrides = IsolationProfileSchema.partial().parse(JSON.parse(raw));
|
|
91
|
+
const tier = opts.tier;
|
|
92
|
+
const profile = resolveProfile(tier, overrides);
|
|
93
|
+
const out = {
|
|
94
|
+
tier,
|
|
95
|
+
profile,
|
|
96
|
+
landlock: buildLandlockPolicy(profile),
|
|
97
|
+
sandboxExec: buildSandboxProfile(profile),
|
|
98
|
+
cgroups: buildCgroupSpec(opts.cgroupName, profile)
|
|
99
|
+
};
|
|
100
|
+
process.stdout.write(JSON.stringify(out, null, 2) + "\n");
|
|
101
|
+
});
|
|
102
|
+
const isDirect = (() => {
|
|
103
|
+
try {
|
|
104
|
+
return process.argv[1]?.endsWith("cli.js") ?? false;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
})();
|
|
110
|
+
if (isDirect) {
|
|
111
|
+
// No args → serve. Matches the behavior of `mcp-rce-guard-server` bin.
|
|
112
|
+
if (process.argv.length <= 2) {
|
|
113
|
+
serverMain().catch((e) => {
|
|
114
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
115
|
+
process.stderr.write(`[mcp-rce-guard] fatal: ${msg}\n`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
program.parseAsync(process.argv).catch((e) => {
|
|
121
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
122
|
+
process.stderr.write(`[mcp-rce-guard cli] error: ${msg}\n`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export { program };
|
|
128
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CVE replay engine.
|
|
3
|
+
*
|
|
4
|
+
* v0.1 ships built-in replay logic for three 2026-CVEs. Each fixture is a
|
|
5
|
+
* deterministic predicate that examines the candidate `targetServerCommand`
|
|
6
|
+
* + the registered subprocess profile and decides if the configuration
|
|
7
|
+
* would be vulnerable. A `pass` verdict means the configuration BLOCKS the
|
|
8
|
+
* vuln class; `fail` means the configuration is still vulnerable.
|
|
9
|
+
*
|
|
10
|
+
* The fixtures are *behavioral predicates*, not exploit payloads, so this
|
|
11
|
+
* package can ship without security-distribution-hygiene flags. The
|
|
12
|
+
* separate `mcp-rce-fixtures` package contains additional offline replay
|
|
13
|
+
* suites for CI use; v0.1 inlines just enough to make the tool useful
|
|
14
|
+
* without requiring the fixtures package.
|
|
15
|
+
*
|
|
16
|
+
* Sources:
|
|
17
|
+
* - MCP-SDK-RCE 22.04.2026 (Cloudflare patch in createMcpHandler)
|
|
18
|
+
* - CVE-2026-27124 (FastMCP Confused Deputy)
|
|
19
|
+
* - Nginx-MCP RCE CVSS 9.8
|
|
20
|
+
*/
|
|
21
|
+
import type { CveId } from "../types.js";
|
|
22
|
+
export interface CveFixture {
|
|
23
|
+
id: CveId;
|
|
24
|
+
description: string;
|
|
25
|
+
predicate: (cmd: string) => CveFixtureResult;
|
|
26
|
+
}
|
|
27
|
+
export interface CveFixtureResult {
|
|
28
|
+
status: "pass" | "fail";
|
|
29
|
+
evidence: string;
|
|
30
|
+
}
|
|
31
|
+
export declare const BUILT_IN_FIXTURES: readonly CveFixture[];
|
|
32
|
+
export declare function getFixture(id: CveId): CveFixture | undefined;
|
|
33
|
+
export interface ReplayPerCve {
|
|
34
|
+
id: CveId;
|
|
35
|
+
status: "pass" | "fail" | "skipped";
|
|
36
|
+
durationMs: number;
|
|
37
|
+
evidence?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ReplayResult {
|
|
40
|
+
overall: "pass" | "fail";
|
|
41
|
+
perCve: ReplayPerCve[];
|
|
42
|
+
}
|
|
43
|
+
export declare function runReplay(targetCommand: string, cveSet?: CveId[], timeoutMs?: number): ReplayResult;
|
|
44
|
+
//# sourceMappingURL=replay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/cve/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,KAAK,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,gBAAgB,CAAC;CAC9C;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoGD,eAAO,MAAM,iBAAiB,EAAE,SAAS,UAAU,EAqElD,CAAC;AAEF,wBAAgB,UAAU,CAAC,EAAE,EAAE,KAAK,GAAG,UAAU,GAAG,SAAS,CAE5D;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,wBAAgB,SAAS,CACvB,aAAa,EAAE,MAAM,EACrB,MAAM,CAAC,EAAE,KAAK,EAAE,EAChB,SAAS,SAAS,GACjB,YAAY,CAqCd"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CVE replay engine.
|
|
3
|
+
*
|
|
4
|
+
* v0.1 ships built-in replay logic for three 2026-CVEs. Each fixture is a
|
|
5
|
+
* deterministic predicate that examines the candidate `targetServerCommand`
|
|
6
|
+
* + the registered subprocess profile and decides if the configuration
|
|
7
|
+
* would be vulnerable. A `pass` verdict means the configuration BLOCKS the
|
|
8
|
+
* vuln class; `fail` means the configuration is still vulnerable.
|
|
9
|
+
*
|
|
10
|
+
* The fixtures are *behavioral predicates*, not exploit payloads, so this
|
|
11
|
+
* package can ship without security-distribution-hygiene flags. The
|
|
12
|
+
* separate `mcp-rce-fixtures` package contains additional offline replay
|
|
13
|
+
* suites for CI use; v0.1 inlines just enough to make the tool useful
|
|
14
|
+
* without requiring the fixtures package.
|
|
15
|
+
*
|
|
16
|
+
* Sources:
|
|
17
|
+
* - MCP-SDK-RCE 22.04.2026 (Cloudflare patch in createMcpHandler)
|
|
18
|
+
* - CVE-2026-27124 (FastMCP Confused Deputy)
|
|
19
|
+
* - Nginx-MCP RCE CVSS 9.8
|
|
20
|
+
*/
|
|
21
|
+
import { normalizeArg } from "../normalize.js";
|
|
22
|
+
/**
|
|
23
|
+
* Allowlist of variable names that are considered safe to embed verbatim in
|
|
24
|
+
* a target command. Anything outside this allowlist gets flagged as
|
|
25
|
+
* potential confused-deputy material by the cve-2026-27124 fixture.
|
|
26
|
+
*
|
|
27
|
+
* Reviewer S1024 F4-Sub-b: previous code used a narrow blocklist
|
|
28
|
+
* (`API_KEY|SECRET|TOKEN|PASSWORD|BEARER`) and missed obvious credentials
|
|
29
|
+
* like `AUTH_HEADER`, `COOKIE`, `SESSION_ID`, `PRIVATE_KEY`, `REFRESH_TOKEN`.
|
|
30
|
+
* Inverting to allowlist closes the entire credential-name surface.
|
|
31
|
+
*/
|
|
32
|
+
const SAFE_ENV_VARS = new Set([
|
|
33
|
+
"HOME",
|
|
34
|
+
"USER",
|
|
35
|
+
"USERNAME",
|
|
36
|
+
"LOGNAME",
|
|
37
|
+
"SHELL",
|
|
38
|
+
"PATH",
|
|
39
|
+
"LANG",
|
|
40
|
+
"LC_ALL",
|
|
41
|
+
"LC_CTYPE",
|
|
42
|
+
"TZ",
|
|
43
|
+
"TERM",
|
|
44
|
+
"TMPDIR",
|
|
45
|
+
"TEMP",
|
|
46
|
+
"TMP",
|
|
47
|
+
"PWD",
|
|
48
|
+
"OLDPWD",
|
|
49
|
+
"HOSTNAME",
|
|
50
|
+
"DISPLAY",
|
|
51
|
+
"EDITOR",
|
|
52
|
+
"PAGER",
|
|
53
|
+
"NODE_ENV",
|
|
54
|
+
"DEBUG",
|
|
55
|
+
"CI"
|
|
56
|
+
]);
|
|
57
|
+
/**
|
|
58
|
+
* Shell binaries that are commonly used to wrap a subprocess and grant it the
|
|
59
|
+
* full inheritance surface that Nginx-MCP RCE (CVSS 9.8) exploits. Broadened
|
|
60
|
+
* per Reviewer S1024 F4-Sub-c — busybox/dash/csh/ksh/fish/tcsh now covered,
|
|
61
|
+
* arbitrary absolute paths covered, indirect invocation (`exec`, `nice`, `env`)
|
|
62
|
+
* covered.
|
|
63
|
+
*/
|
|
64
|
+
const SHELL_BINARIES = [
|
|
65
|
+
"sh",
|
|
66
|
+
"bash",
|
|
67
|
+
"zsh",
|
|
68
|
+
"dash",
|
|
69
|
+
"ksh",
|
|
70
|
+
"csh",
|
|
71
|
+
"tcsh",
|
|
72
|
+
"fish",
|
|
73
|
+
"ash",
|
|
74
|
+
"busybox"
|
|
75
|
+
];
|
|
76
|
+
/**
|
|
77
|
+
* Detect any unquoted shell metacharacter or substitution form anywhere in
|
|
78
|
+
* the command. Covers (Reviewer S1024 F4-Sub-a evidence):
|
|
79
|
+
* - Standalone metachars: `;`, `|`, `&` (single + double), `>`, `<`
|
|
80
|
+
* - Command substitution: backticks `` `cmd` ``
|
|
81
|
+
* - `$(cmd)` substitution
|
|
82
|
+
* - `<<<` here-strings
|
|
83
|
+
* - `${VAR}` and `$VAR` variable expansions adjacent to metachars
|
|
84
|
+
*/
|
|
85
|
+
const SHELL_METACHAR_PATTERNS = [
|
|
86
|
+
{ pattern: /`[^`]*`/, name: "backtick command substitution" },
|
|
87
|
+
{ pattern: /\$\([^)]*\)/, name: "$(...) command substitution" },
|
|
88
|
+
{ pattern: /<<</, name: "here-string redirect (<<<)" },
|
|
89
|
+
{ pattern: /(^|[^\\])[;]/, name: "unescaped semicolon" },
|
|
90
|
+
{ pattern: /(^|[^\\|])\|(?!\|)/, name: "unescaped pipe" },
|
|
91
|
+
{ pattern: /(^|[^\\&])&(?!&)/, name: "unescaped background ampersand" },
|
|
92
|
+
{ pattern: /(^|[^\\])&&/, name: "logical-and operator" },
|
|
93
|
+
{ pattern: /(^|[^\\])\|\|/, name: "logical-or operator" },
|
|
94
|
+
{ pattern: /(^|[^\\])>(?!>)/, name: "stdout redirect" },
|
|
95
|
+
{ pattern: /(^|[^\\])>>/, name: "append redirect" },
|
|
96
|
+
{ pattern: /(^|[^\\])<(?![<])/, name: "stdin redirect" },
|
|
97
|
+
{ pattern: /\$\{[^}]+\}/, name: "${VAR} expansion" },
|
|
98
|
+
{ pattern: /\$[A-Za-z_][A-Za-z0-9_]*/, name: "$VAR expansion" }
|
|
99
|
+
];
|
|
100
|
+
function findShellInvocation(cmd) {
|
|
101
|
+
// Tokenize on whitespace + simple separators so we can spot a shell
|
|
102
|
+
// binary anywhere in the command (not just anchored at the start).
|
|
103
|
+
const tokens = cmd
|
|
104
|
+
.split(/[\s;|&]+/)
|
|
105
|
+
.map((t) => t.trim())
|
|
106
|
+
.filter((t) => t.length > 0);
|
|
107
|
+
for (const token of tokens) {
|
|
108
|
+
// Strip absolute-path prefix to compare just the basename.
|
|
109
|
+
const basename = token.split("/").pop() ?? token;
|
|
110
|
+
if (SHELL_BINARIES.includes(basename)) {
|
|
111
|
+
return token;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
export const BUILT_IN_FIXTURES = [
|
|
117
|
+
{
|
|
118
|
+
id: "mcp-sdk-rce-2026-04-22",
|
|
119
|
+
description: "MCP-SDK ungesanitized Tool-Args fed into shell command. Predicate: command must NOT contain ANY shell metacharacters or substitution forms (broadened per Reviewer S1024 F4-Sub-a — covers ;, |, &, &&, ||, backticks, $(), <<<, redirects, ${VAR}, $VAR).",
|
|
120
|
+
predicate: (cmd) => {
|
|
121
|
+
for (const { pattern, name } of SHELL_METACHAR_PATTERNS) {
|
|
122
|
+
if (pattern.test(cmd)) {
|
|
123
|
+
return {
|
|
124
|
+
status: "fail",
|
|
125
|
+
evidence: `command contains ${name} (${cmd}) — shell-injection class`
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
status: "pass",
|
|
131
|
+
evidence: "no shell metacharacters or substitution forms detected"
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: "cve-2026-27124",
|
|
137
|
+
description: "FastMCP Confused Deputy — server forwards caller-controlled token to downstream. Predicate: any embedded `${VAR}` or `$VAR` must be in the SAFE_ENV_VARS allowlist (Reviewer S1024 F4-Sub-b — invert to allowlist).",
|
|
138
|
+
predicate: (cmd) => {
|
|
139
|
+
// Match both ${VAR_NAME} and $VAR_NAME forms.
|
|
140
|
+
const bracedRe = /\$\{([A-Za-z_][A-Za-z0-9_]*)[^}]*\}/g;
|
|
141
|
+
const bareRe = /\$([A-Za-z_][A-Za-z0-9_]*)\b/g;
|
|
142
|
+
const flagged = [];
|
|
143
|
+
for (const re of [bracedRe, bareRe]) {
|
|
144
|
+
let m;
|
|
145
|
+
while ((m = re.exec(cmd)) !== null) {
|
|
146
|
+
const name = m[1];
|
|
147
|
+
if (name && !SAFE_ENV_VARS.has(name)) {
|
|
148
|
+
flagged.push(name);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (flagged.length > 0) {
|
|
153
|
+
const list = Array.from(new Set(flagged)).join(", ");
|
|
154
|
+
return {
|
|
155
|
+
status: "fail",
|
|
156
|
+
evidence: `command embeds non-allowlisted env-var(s): ${list} — potential confused-deputy class`
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
status: "pass",
|
|
161
|
+
evidence: "no non-allowlisted env-vars embedded in command"
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "nginx-mcp-rce-9.8",
|
|
167
|
+
description: "Nginx-MCP RCE CVSS 9.8 — bridge-server spawns subprocess inheriting full parent permissions. Predicate: no shell binary may appear anywhere in the command, regardless of path/invocation form (broadened per Reviewer S1024 F4-Sub-c — busybox/dash/csh/ksh/fish/tcsh covered, arbitrary paths covered, indirect invocation covered).",
|
|
168
|
+
predicate: (cmd) => {
|
|
169
|
+
const found = findShellInvocation(cmd);
|
|
170
|
+
if (found !== null) {
|
|
171
|
+
return {
|
|
172
|
+
status: "fail",
|
|
173
|
+
evidence: `command invokes shell binary "${found}" — RCE-bridge class`
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
status: "pass",
|
|
178
|
+
evidence: "no shell binary invocation detected"
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
];
|
|
183
|
+
export function getFixture(id) {
|
|
184
|
+
return BUILT_IN_FIXTURES.find((f) => f.id === id);
|
|
185
|
+
}
|
|
186
|
+
export function runReplay(targetCommand, cveSet, timeoutMs = 30_000) {
|
|
187
|
+
// Reviewer F3 (Session post-S1056): pre-normalize the target command before
|
|
188
|
+
// feeding it to predicates. NFKC + ZWC-strip + Bidi-block ensures
|
|
189
|
+
// Fullwidth-Unicode-Bypass payloads like `$(rm -rf /)` collapse to
|
|
190
|
+
// `$(rm -rf /)` and trigger SHELL_METACHAR_PATTERNS. Without this step,
|
|
191
|
+
// `scan_cve_replay` returned false-negatives on the simulate_attacker_input
|
|
192
|
+
// fullwidth-unicode corpus that README §13 explicitly claims to cover.
|
|
193
|
+
// The audit_subprocess path already normalizes via Pillar-8 shared normalize.ts;
|
|
194
|
+
// this aligns scan_cve_replay with the same canonical form.
|
|
195
|
+
const normalizedCommand = normalizeArg(targetCommand);
|
|
196
|
+
const ids = cveSet ?? BUILT_IN_FIXTURES.map((f) => f.id);
|
|
197
|
+
const perCve = [];
|
|
198
|
+
const startAll = Date.now();
|
|
199
|
+
for (const id of ids) {
|
|
200
|
+
const fixture = getFixture(id);
|
|
201
|
+
if (!fixture) {
|
|
202
|
+
perCve.push({ id, status: "skipped", durationMs: 0, evidence: "unknown fixture id" });
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (Date.now() - startAll > timeoutMs) {
|
|
206
|
+
perCve.push({ id, status: "skipped", durationMs: 0, evidence: "timeout" });
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const start = Date.now();
|
|
210
|
+
const result = fixture.predicate(normalizedCommand);
|
|
211
|
+
perCve.push({
|
|
212
|
+
id,
|
|
213
|
+
status: result.status,
|
|
214
|
+
durationMs: Date.now() - start,
|
|
215
|
+
evidence: result.evidence
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
const overall = perCve.every((r) => r.status !== "fail") ? "pass" : "fail";
|
|
219
|
+
return { overall, perCve };
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/cve/replay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Egress policy evaluation.
|
|
3
|
+
*
|
|
4
|
+
* Default-deny: a host:port is allowed only if it matches an entry in the
|
|
5
|
+
* allowlist. Wildcard "*" allows all (audit-only mode). Subdomain matching
|
|
6
|
+
* uses literal suffix-with-dot (no glob).
|
|
7
|
+
*
|
|
8
|
+
* Pre-Publish-Audit F7: host strings on both sides of the match are first
|
|
9
|
+
* NFKC + zero-width-strip + bidi-block normalized via Pillar-8 normalize.ts
|
|
10
|
+
* and lowercased, so a fullwidth-unicode hostname (e.g. `example.com`)
|
|
11
|
+
* cannot smuggle past an allowlist that lists the ASCII form.
|
|
12
|
+
*/
|
|
13
|
+
export interface EgressDecision {
|
|
14
|
+
allowed: boolean;
|
|
15
|
+
reason: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Evaluate whether a host:port pair is allowed by the allowlist.
|
|
19
|
+
*
|
|
20
|
+
* Allowlist entry forms:
|
|
21
|
+
* - "*" → allow all (used in audit-only mode)
|
|
22
|
+
* - "example.com:443" → exact host:port match
|
|
23
|
+
* - ".example.com:443"→ suffix match (any subdomain)
|
|
24
|
+
* - "example.com:*" → host match, any port
|
|
25
|
+
*/
|
|
26
|
+
export declare function evaluateEgress(host: string, port: number, allowlist: readonly string[]): EgressDecision;
|
|
27
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/egress/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAWD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,cAAc,CAchB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Egress policy evaluation.
|
|
3
|
+
*
|
|
4
|
+
* Default-deny: a host:port is allowed only if it matches an entry in the
|
|
5
|
+
* allowlist. Wildcard "*" allows all (audit-only mode). Subdomain matching
|
|
6
|
+
* uses literal suffix-with-dot (no glob).
|
|
7
|
+
*
|
|
8
|
+
* Pre-Publish-Audit F7: host strings on both sides of the match are first
|
|
9
|
+
* NFKC + zero-width-strip + bidi-block normalized via Pillar-8 normalize.ts
|
|
10
|
+
* and lowercased, so a fullwidth-unicode hostname (e.g. `example.com`)
|
|
11
|
+
* cannot smuggle past an allowlist that lists the ASCII form.
|
|
12
|
+
*/
|
|
13
|
+
import { normalizeArg } from "../normalize.js";
|
|
14
|
+
/**
|
|
15
|
+
* Canonicalize a host string: NFKC + invisible-codepoint strip via the
|
|
16
|
+
* shared normalize pipeline, then lowercase. Used on both allowlist entries
|
|
17
|
+
* and the candidate host so matching is locale-stable and unicode-safe.
|
|
18
|
+
*/
|
|
19
|
+
function canonicalHost(host) {
|
|
20
|
+
return normalizeArg(host).toLowerCase();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Evaluate whether a host:port pair is allowed by the allowlist.
|
|
24
|
+
*
|
|
25
|
+
* Allowlist entry forms:
|
|
26
|
+
* - "*" → allow all (used in audit-only mode)
|
|
27
|
+
* - "example.com:443" → exact host:port match
|
|
28
|
+
* - ".example.com:443"→ suffix match (any subdomain)
|
|
29
|
+
* - "example.com:*" → host match, any port
|
|
30
|
+
*/
|
|
31
|
+
export function evaluateEgress(host, port, allowlist) {
|
|
32
|
+
if (!host || !Number.isFinite(port) || port < 0 || port > 65535) {
|
|
33
|
+
return { allowed: false, reason: "invalid host or port" };
|
|
34
|
+
}
|
|
35
|
+
if (allowlist.includes("*")) {
|
|
36
|
+
return { allowed: true, reason: "wildcard allow" };
|
|
37
|
+
}
|
|
38
|
+
const candidate = canonicalHost(host);
|
|
39
|
+
for (const entry of allowlist) {
|
|
40
|
+
if (matches(candidate, port, entry)) {
|
|
41
|
+
return { allowed: true, reason: `match: ${entry}` };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { allowed: false, reason: "default-deny: no allowlist match" };
|
|
45
|
+
}
|
|
46
|
+
function matches(host, port, entry) {
|
|
47
|
+
const colonIdx = entry.lastIndexOf(":");
|
|
48
|
+
if (colonIdx < 0)
|
|
49
|
+
return false;
|
|
50
|
+
const entryHost = canonicalHost(entry.slice(0, colonIdx));
|
|
51
|
+
const entryPort = entry.slice(colonIdx + 1);
|
|
52
|
+
// Port match
|
|
53
|
+
if (entryPort !== "*" && entryPort !== String(port)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
// Host match (both sides already canonicalized).
|
|
57
|
+
if (entryHost.startsWith(".")) {
|
|
58
|
+
return host.endsWith(entryHost) || host === entryHost.slice(1);
|
|
59
|
+
}
|
|
60
|
+
return host === entryHost;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/egress/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAO/C;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,IAAY,EACZ,SAA4B;IAE5B,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QAChE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;IAC5D,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACrD,CAAC;IACD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC;AACxE,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,IAAY,EAAE,KAAa;IACxD,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/B,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAE5C,aAAa;IACb,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,iDAAiD;IACjD,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,IAAI,KAAK,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,IAAI,KAAK,SAAS,CAAC;AAC5B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcp-rce-guard — public library entrypoint.
|
|
3
|
+
*
|
|
4
|
+
* This module re-exports the building blocks for callers that want to
|
|
5
|
+
* embed mcp-rce-guard in their own MCP server / CLI tool.
|
|
6
|
+
*/
|
|
7
|
+
export { NAME, VERSION } from "./version.js";
|
|
8
|
+
export { IsolationProfileSchema, RegisterSubprocessArgsSchema, AuditSubprocessArgsSchema, ScanCveReplayArgsSchema, TrackCanaryArgsSchema, InjectEgressPolicyArgsSchema, GetAuditLogArgsSchema, TrustTierSchema, CveIdSchema, EgressModeSchema, AuditVerdict, type IsolationProfile, type RegisterSubprocessArgs, type AuditSubprocessArgs, type ScanCveReplayArgs, type TrackCanaryArgs, type InjectEgressPolicyArgs, type GetAuditLogArgs, type AuditLogEntry, type RegisteredSubprocess, type AuditVerdictType, type CveId, type EgressMode } from "./types.js";
|
|
9
|
+
export { normalizeArg, normalizeArgs, hasInvisibleCodepoints } from "./normalize.js";
|
|
10
|
+
export { TRUST_TIER_DEFAULTS, resolveProfile, type TrustTier } from "./trust-tiers.js";
|
|
11
|
+
export { detectPlatform, type PlatformInfo, type IsolationBackend } from "./isolation/platform.js";
|
|
12
|
+
export { buildLandlockPolicy, policyAllowsExec } from "./isolation/landlock.js";
|
|
13
|
+
export type { LandlockPolicyDescriptor } from "./isolation/landlock.js";
|
|
14
|
+
export { buildSandboxProfile } from "./isolation/sandbox-exec.js";
|
|
15
|
+
export { buildCgroupSpec, type CgroupSpec } from "./isolation/cgroups.js";
|
|
16
|
+
export { makeCanary, detectLeaks, type LeakChannel, type LeakLocation, type CorpusEntry } from "./canary/tracker.js";
|
|
17
|
+
export { runReplay, BUILT_IN_FIXTURES, getFixture, type CveFixture, type ReplayResult, type ReplayPerCve } from "./cve/replay.js";
|
|
18
|
+
export { evaluateEgress, type EgressDecision } from "./egress/policy.js";
|
|
19
|
+
export { appendAudit, readAudit, auditLogPath } from "./audit/log.js";
|
|
20
|
+
export { registerSubprocessTool, type RegisterSubprocessResult } from "./tools/register.js";
|
|
21
|
+
export { auditSubprocessTool, type AuditSubprocessResult } from "./tools/audit.js";
|
|
22
|
+
export { scanCveReplayTool } from "./tools/scanCve.js";
|
|
23
|
+
export { trackCanaryTool, type TrackCanaryResult } from "./tools/trackCanary.js";
|
|
24
|
+
export { injectEgressPolicyTool, type InjectEgressPolicyResult } from "./tools/injectEgress.js";
|
|
25
|
+
export { getAuditLogTool, type GetAuditLogResult } from "./tools/getAuditLog.js";
|
|
26
|
+
export { clearRegistry } from "./state.js";
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG7C,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,EAC5B,qBAAqB,EACrB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,KAAK,EACV,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAGrF,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChF,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAG1E,OAAO,EACL,UAAU,EACV,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAKzE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGtE,OAAO,EACL,sBAAsB,EACtB,KAAK,wBAAwB,EAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,KAAK,qBAAqB,EAC3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EACL,eAAe,EACf,KAAK,iBAAiB,EACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,sBAAsB,EACtB,KAAK,wBAAwB,EAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,eAAe,EACf,KAAK,iBAAiB,EACvB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcp-rce-guard — public library entrypoint.
|
|
3
|
+
*
|
|
4
|
+
* This module re-exports the building blocks for callers that want to
|
|
5
|
+
* embed mcp-rce-guard in their own MCP server / CLI tool.
|
|
6
|
+
*/
|
|
7
|
+
export { NAME, VERSION } from "./version.js";
|
|
8
|
+
// Types + schemas
|
|
9
|
+
export { IsolationProfileSchema, RegisterSubprocessArgsSchema, AuditSubprocessArgsSchema, ScanCveReplayArgsSchema, TrackCanaryArgsSchema, InjectEgressPolicyArgsSchema, GetAuditLogArgsSchema, TrustTierSchema, CveIdSchema, EgressModeSchema, AuditVerdict } from "./types.js";
|
|
10
|
+
// Normalize (Pillar-8-shared)
|
|
11
|
+
export { normalizeArg, normalizeArgs, hasInvisibleCodepoints } from "./normalize.js";
|
|
12
|
+
// Trust tiers
|
|
13
|
+
export { TRUST_TIER_DEFAULTS, resolveProfile } from "./trust-tiers.js";
|
|
14
|
+
// Isolation backends
|
|
15
|
+
export { detectPlatform } from "./isolation/platform.js";
|
|
16
|
+
export { buildLandlockPolicy, policyAllowsExec } from "./isolation/landlock.js";
|
|
17
|
+
export { buildSandboxProfile } from "./isolation/sandbox-exec.js";
|
|
18
|
+
export { buildCgroupSpec } from "./isolation/cgroups.js";
|
|
19
|
+
// Canary
|
|
20
|
+
export { makeCanary, detectLeaks } from "./canary/tracker.js";
|
|
21
|
+
// CVE replay
|
|
22
|
+
export { runReplay, BUILT_IN_FIXTURES, getFixture } from "./cve/replay.js";
|
|
23
|
+
// Egress
|
|
24
|
+
export { evaluateEgress } from "./egress/policy.js";
|
|
25
|
+
// Audit log
|
|
26
|
+
// Note: `clearAuditLog` is intentionally NOT re-exported here (Pre-Publish-Audit F9).
|
|
27
|
+
// It is a @internal test helper; tests import it directly from "./audit/log.js".
|
|
28
|
+
export { appendAudit, readAudit, auditLogPath } from "./audit/log.js";
|
|
29
|
+
// Tools (programmatic access — same handlers the MCP server registers)
|
|
30
|
+
export { registerSubprocessTool } from "./tools/register.js";
|
|
31
|
+
export { auditSubprocessTool } from "./tools/audit.js";
|
|
32
|
+
export { scanCveReplayTool } from "./tools/scanCve.js";
|
|
33
|
+
export { trackCanaryTool } from "./tools/trackCanary.js";
|
|
34
|
+
export { injectEgressPolicyTool } from "./tools/injectEgress.js";
|
|
35
|
+
export { getAuditLogTool } from "./tools/getAuditLog.js";
|
|
36
|
+
// State (test-only escape hatch — guarded by name)
|
|
37
|
+
export { clearRegistry } from "./state.js";
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE7C,kBAAkB;AAClB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,EAC5B,qBAAqB,EACrB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,YAAY,EAab,MAAM,YAAY,CAAC;AAEpB,8BAA8B;AAC9B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAErF,cAAc;AACd,OAAO,EACL,mBAAmB,EACnB,cAAc,EAEf,MAAM,kBAAkB,CAAC;AAE1B,qBAAqB;AACrB,OAAO,EACL,cAAc,EAGf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhF,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAmB,MAAM,wBAAwB,CAAC;AAE1E,SAAS;AACT,OAAO,EACL,UAAU,EACV,WAAW,EAIZ,MAAM,qBAAqB,CAAC;AAE7B,aAAa;AACb,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,UAAU,EAIX,MAAM,iBAAiB,CAAC;AAEzB,SAAS;AACT,OAAO,EAAE,cAAc,EAAuB,MAAM,oBAAoB,CAAC;AAEzE,YAAY;AACZ,sFAAsF;AACtF,iFAAiF;AACjF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEtE,uEAAuE;AACvE,OAAO,EACL,sBAAsB,EAEvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EAEpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EACL,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,sBAAsB,EAEvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAEhC,mDAAmD;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cgroups-v2 resource cap synthesis.
|
|
3
|
+
*
|
|
4
|
+
* v0.1 emits a *spec* listing the files-to-write and values. The actual
|
|
5
|
+
* write happens in the spawning helper (separation-of-concerns: we don't
|
|
6
|
+
* want to write to /sys/fs/cgroup from inside a tool handler — that needs
|
|
7
|
+
* elevated privileges that the MCP server typically lacks).
|
|
8
|
+
*/
|
|
9
|
+
import type { IsolationProfile } from "../types.js";
|
|
10
|
+
export interface CgroupSpec {
|
|
11
|
+
/** cgroup v2 path under /sys/fs/cgroup. The spawner creates it. */
|
|
12
|
+
cgroupPath: string;
|
|
13
|
+
/** key/value writes the spawner must perform. */
|
|
14
|
+
writes: Array<{
|
|
15
|
+
file: string;
|
|
16
|
+
value: string;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
export declare function buildCgroupSpec(cgroupName: string, profile: IsolationProfile): CgroupSpec;
|
|
20
|
+
//# sourceMappingURL=cgroups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cgroups.d.ts","sourceRoot":"","sources":["../../src/isolation/cgroups.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,GACxB,UAAU,CAyBZ"}
|