@mneme-ai/core 2.59.0 → 2.60.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/dist/agent_manifest.d.ts.map +1 -1
- package/dist/agent_manifest.js +6 -0
- package/dist/agent_manifest.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/skeleton_key/bypass_graph.d.ts +56 -0
- package/dist/skeleton_key/bypass_graph.d.ts.map +1 -0
- package/dist/skeleton_key/bypass_graph.js +89 -0
- package/dist/skeleton_key/bypass_graph.js.map +1 -0
- package/dist/skeleton_key/capability_probe.d.ts +58 -0
- package/dist/skeleton_key/capability_probe.d.ts.map +1 -0
- package/dist/skeleton_key/capability_probe.js +149 -0
- package/dist/skeleton_key/capability_probe.js.map +1 -0
- package/dist/skeleton_key/index.d.ts +142 -0
- package/dist/skeleton_key/index.d.ts.map +1 -0
- package/dist/skeleton_key/index.js +321 -0
- package/dist/skeleton_key/index.js.map +1 -0
- package/dist/skeleton_key/risk_heuristics.d.ts +46 -0
- package/dist/skeleton_key/risk_heuristics.d.ts.map +1 -0
- package/dist/skeleton_key/risk_heuristics.js +206 -0
- package/dist/skeleton_key/risk_heuristics.js.map +1 -0
- package/dist/truth_gate/claims.d.ts.map +1 -1
- package/dist/truth_gate/claims.js +19 -0
- package/dist/truth_gate/claims.js.map +1 -1
- package/dist/truth_gate/probes.d.ts.map +1 -1
- package/dist/truth_gate/probes.js +48 -0
- package/dist/truth_gate/probes.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.60.0 — SKELETON KEY: MCP server security auditor.
|
|
3
|
+
*
|
|
4
|
+
* MCP ecosystem reality (2026): ~500+ servers, mostly community-built,
|
|
5
|
+
* no central security review. Users wire 5-15 servers into Claude
|
|
6
|
+
* Desktop / Cursor / Continue / Cline without realizing the
|
|
7
|
+
* UNION of their capabilities = a much larger attack surface than any
|
|
8
|
+
* individual server.
|
|
9
|
+
*
|
|
10
|
+
* SKELETON KEY is the first MCP security auditor. Five wild innovations:
|
|
11
|
+
*
|
|
12
|
+
* 1. EMPIRICAL CAPABILITY PROBE — spawn each MCP server + read its
|
|
13
|
+
* real tools/list (not name-guess). Hand-written rules can lie;
|
|
14
|
+
* a tools/list cannot.
|
|
15
|
+
*
|
|
16
|
+
* 2. TRANSITIVE BYPASS GRAPH — model servers as graph nodes; edges =
|
|
17
|
+
* capability overlap; compute paths to attacker goals (delete_repo,
|
|
18
|
+
* exfiltrate_secret, drop_database, etc). Most audit tools stop at
|
|
19
|
+
* single-server analysis. We compute the graph.
|
|
20
|
+
*
|
|
21
|
+
* 3. HMAC CONFIG PINNING — snapshot the user's MCP configs; detect
|
|
22
|
+
* tampering / silent new-server-added on next audit. Tamper-evident
|
|
23
|
+
* drift report.
|
|
24
|
+
*
|
|
25
|
+
* 4. RISK BUDGET — single score 0..N quantifying total surface. User
|
|
26
|
+
* sets a budget (e.g. 5.0); new servers that push over budget are
|
|
27
|
+
* refused at install time.
|
|
28
|
+
*
|
|
29
|
+
* 5. CWE COMPLIANCE MAPPING — every finding maps to a CWE id, making
|
|
30
|
+
* the output audit-grade for security teams.
|
|
31
|
+
*
|
|
32
|
+
* Pure ESM. Defensive — never throws on disk / parse / spawn errors.
|
|
33
|
+
*/
|
|
34
|
+
import { type RiskHeuristic } from "./risk_heuristics.js";
|
|
35
|
+
import { type BypassGraph } from "./bypass_graph.js";
|
|
36
|
+
export interface McpServerConfig {
|
|
37
|
+
/** Server name (key in the host's mcpServers map). */
|
|
38
|
+
name: string;
|
|
39
|
+
/** spawn command. */
|
|
40
|
+
command?: string;
|
|
41
|
+
/** spawn args. */
|
|
42
|
+
args?: string[];
|
|
43
|
+
/** env map. */
|
|
44
|
+
env?: Record<string, string>;
|
|
45
|
+
/** Source file the config came from. */
|
|
46
|
+
source: string;
|
|
47
|
+
}
|
|
48
|
+
export interface SkeletonKeyAudit {
|
|
49
|
+
ok: boolean;
|
|
50
|
+
at: string;
|
|
51
|
+
totalServers: number;
|
|
52
|
+
/** All distinct config files that contributed servers. */
|
|
53
|
+
sources: string[];
|
|
54
|
+
/** Per-server risk findings, sorted by severity desc. */
|
|
55
|
+
findings: Array<{
|
|
56
|
+
server: string;
|
|
57
|
+
risk: RiskHeuristic;
|
|
58
|
+
/** "heuristic" if matched by name; "empirical" if capability-probe upgraded. */
|
|
59
|
+
source: "heuristic" | "empirical" | "unknown";
|
|
60
|
+
/** When empirical, the tool count we discovered. */
|
|
61
|
+
toolCount?: number;
|
|
62
|
+
}>;
|
|
63
|
+
/** Capability overlaps + bypass paths. */
|
|
64
|
+
graph: BypassGraph;
|
|
65
|
+
/** Total risk budget score (sum). */
|
|
66
|
+
riskBudget: number;
|
|
67
|
+
/** User-set budget cap (default 5.0). */
|
|
68
|
+
budgetCap: number;
|
|
69
|
+
/** True iff riskBudget ≤ budgetCap. */
|
|
70
|
+
withinBudget: boolean;
|
|
71
|
+
/** Plain-English summary. */
|
|
72
|
+
summary: string;
|
|
73
|
+
/** HMAC seal of the audit body for tamper detection. */
|
|
74
|
+
hmac: string;
|
|
75
|
+
}
|
|
76
|
+
export interface AuditOpts {
|
|
77
|
+
/** Override discovery paths. */
|
|
78
|
+
configPaths?: string[];
|
|
79
|
+
/** Set the budget cap (default 5.0). */
|
|
80
|
+
budgetCap?: number;
|
|
81
|
+
/** Run empirical capability probe on each server (slow; ~1-2s per server). */
|
|
82
|
+
empiricalProbe?: boolean;
|
|
83
|
+
/** Limit empirical probe to specific server names. */
|
|
84
|
+
probeOnly?: string[];
|
|
85
|
+
}
|
|
86
|
+
/** Default paths for Claude Desktop / Cursor / Continue / Cline configs. */
|
|
87
|
+
export declare function defaultConfigPaths(): string[];
|
|
88
|
+
/**
|
|
89
|
+
* Read each config file, extract MCP server declarations.
|
|
90
|
+
* Tolerates multiple known schemas: claude_desktop, cursor settings,
|
|
91
|
+
* continue, cline, windsurf.
|
|
92
|
+
*/
|
|
93
|
+
export declare function discoverServers(configPaths: string[]): McpServerConfig[];
|
|
94
|
+
export declare function auditMcpConfigs(opts?: AuditOpts): Promise<SkeletonKeyAudit>;
|
|
95
|
+
export declare function verifyAudit(a: SkeletonKeyAudit): boolean;
|
|
96
|
+
export interface ConfigSnapshot {
|
|
97
|
+
at: string;
|
|
98
|
+
/** SHA-like digest of every discovered server (deterministic). */
|
|
99
|
+
servers: Array<{
|
|
100
|
+
name: string;
|
|
101
|
+
commandHash: string;
|
|
102
|
+
source: string;
|
|
103
|
+
}>;
|
|
104
|
+
hmac: string;
|
|
105
|
+
}
|
|
106
|
+
export declare function pinConfigSnapshot(cwd: string, configPaths?: string[]): ConfigSnapshot;
|
|
107
|
+
export interface DriftReport {
|
|
108
|
+
ok: boolean;
|
|
109
|
+
hasSnapshot: boolean;
|
|
110
|
+
added: Array<{
|
|
111
|
+
name: string;
|
|
112
|
+
source: string;
|
|
113
|
+
}>;
|
|
114
|
+
removed: Array<{
|
|
115
|
+
name: string;
|
|
116
|
+
source: string;
|
|
117
|
+
}>;
|
|
118
|
+
modified: Array<{
|
|
119
|
+
name: string;
|
|
120
|
+
oldHash: string;
|
|
121
|
+
newHash: string;
|
|
122
|
+
}>;
|
|
123
|
+
snapshotAt?: string;
|
|
124
|
+
currentAt: string;
|
|
125
|
+
hint: string;
|
|
126
|
+
}
|
|
127
|
+
export declare function detectConfigDrift(cwd: string, configPaths?: string[]): DriftReport;
|
|
128
|
+
export interface Recommendation {
|
|
129
|
+
server: string;
|
|
130
|
+
severity: number;
|
|
131
|
+
cwe: string;
|
|
132
|
+
action: string;
|
|
133
|
+
}
|
|
134
|
+
export declare function buildRecommendations(audit: SkeletonKeyAudit): Recommendation[];
|
|
135
|
+
export declare function renderAuditBanner(a: SkeletonKeyAudit): string;
|
|
136
|
+
export { RISK_HEURISTICS, UNKNOWN_HEURISTIC, matchHeuristic } from "./risk_heuristics.js";
|
|
137
|
+
export type { RiskHeuristic } from "./risk_heuristics.js";
|
|
138
|
+
export { buildBypassGraph, totalRiskBudget } from "./bypass_graph.js";
|
|
139
|
+
export type { BypassGraph, BypassPath, CapabilityOverlap, ServerNode } from "./bypass_graph.js";
|
|
140
|
+
export { probeServer } from "./capability_probe.js";
|
|
141
|
+
export type { ProbeInput, ProbeResult, ProbedTool } from "./capability_probe.js";
|
|
142
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skeleton_key/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.60.0 — SKELETON KEY: MCP server security auditor.
|
|
3
|
+
*
|
|
4
|
+
* MCP ecosystem reality (2026): ~500+ servers, mostly community-built,
|
|
5
|
+
* no central security review. Users wire 5-15 servers into Claude
|
|
6
|
+
* Desktop / Cursor / Continue / Cline without realizing the
|
|
7
|
+
* UNION of their capabilities = a much larger attack surface than any
|
|
8
|
+
* individual server.
|
|
9
|
+
*
|
|
10
|
+
* SKELETON KEY is the first MCP security auditor. Five wild innovations:
|
|
11
|
+
*
|
|
12
|
+
* 1. EMPIRICAL CAPABILITY PROBE — spawn each MCP server + read its
|
|
13
|
+
* real tools/list (not name-guess). Hand-written rules can lie;
|
|
14
|
+
* a tools/list cannot.
|
|
15
|
+
*
|
|
16
|
+
* 2. TRANSITIVE BYPASS GRAPH — model servers as graph nodes; edges =
|
|
17
|
+
* capability overlap; compute paths to attacker goals (delete_repo,
|
|
18
|
+
* exfiltrate_secret, drop_database, etc). Most audit tools stop at
|
|
19
|
+
* single-server analysis. We compute the graph.
|
|
20
|
+
*
|
|
21
|
+
* 3. HMAC CONFIG PINNING — snapshot the user's MCP configs; detect
|
|
22
|
+
* tampering / silent new-server-added on next audit. Tamper-evident
|
|
23
|
+
* drift report.
|
|
24
|
+
*
|
|
25
|
+
* 4. RISK BUDGET — single score 0..N quantifying total surface. User
|
|
26
|
+
* sets a budget (e.g. 5.0); new servers that push over budget are
|
|
27
|
+
* refused at install time.
|
|
28
|
+
*
|
|
29
|
+
* 5. CWE COMPLIANCE MAPPING — every finding maps to a CWE id, making
|
|
30
|
+
* the output audit-grade for security teams.
|
|
31
|
+
*
|
|
32
|
+
* Pure ESM. Defensive — never throws on disk / parse / spawn errors.
|
|
33
|
+
*/
|
|
34
|
+
import { createHmac } from "node:crypto";
|
|
35
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
36
|
+
import { homedir, platform } from "node:os";
|
|
37
|
+
import { dirname, join } from "node:path";
|
|
38
|
+
import { UNKNOWN_HEURISTIC, matchHeuristic, } from "./risk_heuristics.js";
|
|
39
|
+
import { buildBypassGraph, totalRiskBudget, } from "./bypass_graph.js";
|
|
40
|
+
import { probeServer } from "./capability_probe.js";
|
|
41
|
+
const KEY_ENV = "MNEME_SKELETON_KEY";
|
|
42
|
+
const DEFAULT_KEY = "mneme-skeleton-key-v1";
|
|
43
|
+
function keyOf() { return process.env[KEY_ENV] ?? DEFAULT_KEY; }
|
|
44
|
+
/** Default paths for Claude Desktop / Cursor / Continue / Cline configs. */
|
|
45
|
+
export function defaultConfigPaths() {
|
|
46
|
+
const home = homedir();
|
|
47
|
+
const paths = [];
|
|
48
|
+
const plat = platform();
|
|
49
|
+
if (plat === "darwin") {
|
|
50
|
+
paths.push(join(home, "Library/Application Support/Claude/claude_desktop_config.json"));
|
|
51
|
+
paths.push(join(home, "Library/Application Support/Cursor/User/settings.json"));
|
|
52
|
+
}
|
|
53
|
+
else if (plat === "win32") {
|
|
54
|
+
const appdata = process.env["APPDATA"] ?? join(home, "AppData/Roaming");
|
|
55
|
+
paths.push(join(appdata, "Claude/claude_desktop_config.json"));
|
|
56
|
+
paths.push(join(appdata, "Cursor/User/settings.json"));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
paths.push(join(home, ".config/Claude/claude_desktop_config.json"));
|
|
60
|
+
paths.push(join(home, ".config/Cursor/User/settings.json"));
|
|
61
|
+
}
|
|
62
|
+
paths.push(join(home, ".continue/config.json"));
|
|
63
|
+
paths.push(join(home, ".cline/config.json"));
|
|
64
|
+
paths.push(join(home, ".codeium/windsurf/mcp_config.json"));
|
|
65
|
+
return paths;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Read each config file, extract MCP server declarations.
|
|
69
|
+
* Tolerates multiple known schemas: claude_desktop, cursor settings,
|
|
70
|
+
* continue, cline, windsurf.
|
|
71
|
+
*/
|
|
72
|
+
export function discoverServers(configPaths) {
|
|
73
|
+
const out = [];
|
|
74
|
+
for (const p of configPaths) {
|
|
75
|
+
if (!existsSync(p))
|
|
76
|
+
continue;
|
|
77
|
+
let parsed = null;
|
|
78
|
+
try {
|
|
79
|
+
parsed = JSON.parse(readFileSync(p, "utf8"));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (!parsed)
|
|
85
|
+
continue;
|
|
86
|
+
const candidates = [
|
|
87
|
+
parsed["mcpServers"],
|
|
88
|
+
parsed["claude.mcpServers"],
|
|
89
|
+
parsed["mcp"]?.["servers"],
|
|
90
|
+
parsed["mcp"]?.["mcpServers"],
|
|
91
|
+
];
|
|
92
|
+
for (const block of candidates) {
|
|
93
|
+
if (!block || typeof block !== "object")
|
|
94
|
+
continue;
|
|
95
|
+
for (const [name, raw] of Object.entries(block)) {
|
|
96
|
+
if (!raw || typeof raw !== "object")
|
|
97
|
+
continue;
|
|
98
|
+
const r = raw;
|
|
99
|
+
out.push({
|
|
100
|
+
name,
|
|
101
|
+
command: typeof r.command === "string" ? r.command : undefined,
|
|
102
|
+
args: Array.isArray(r.args) ? r.args.filter((x) => typeof x === "string") : undefined,
|
|
103
|
+
env: r.env && typeof r.env === "object" ? r.env : undefined,
|
|
104
|
+
source: p,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Deduplicate by name (later sources win — convention: most recent IDE wins).
|
|
110
|
+
const dedup = new Map();
|
|
111
|
+
for (const s of out)
|
|
112
|
+
dedup.set(s.name, s);
|
|
113
|
+
return Array.from(dedup.values());
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Promote a heuristic risk with an empirical capability list. We MERGE
|
|
117
|
+
* (empirical wins on overlap, retain heuristic for tags we didn't see).
|
|
118
|
+
*/
|
|
119
|
+
function promoteRiskWithProbe(base, probe) {
|
|
120
|
+
if (!probe.reachable || probe.capabilities.length === 0)
|
|
121
|
+
return base;
|
|
122
|
+
const mergedCaps = Array.from(new Set([...probe.capabilities, ...base.capabilities]));
|
|
123
|
+
// If empirical exposes more dangerous capabilities than heuristic suggested,
|
|
124
|
+
// bump the severity slightly.
|
|
125
|
+
const hasExec = probe.capabilities.includes("exec");
|
|
126
|
+
const hasWrite = probe.capabilities.includes("write_fs") || probe.capabilities.includes("db_write") || probe.capabilities.includes("db_ddl");
|
|
127
|
+
let severity = base.severity;
|
|
128
|
+
if (hasExec && base.severity < 0.85)
|
|
129
|
+
severity = Math.max(severity, 0.92);
|
|
130
|
+
else if (hasWrite && base.severity < 0.65)
|
|
131
|
+
severity = Math.max(severity, 0.72);
|
|
132
|
+
return { ...base, severity, capabilities: mergedCaps };
|
|
133
|
+
}
|
|
134
|
+
export async function auditMcpConfigs(opts = {}) {
|
|
135
|
+
const at = new Date().toISOString();
|
|
136
|
+
const paths = opts.configPaths ?? defaultConfigPaths();
|
|
137
|
+
const servers = discoverServers(paths);
|
|
138
|
+
const budgetCap = opts.budgetCap ?? 5.0;
|
|
139
|
+
const findings = [];
|
|
140
|
+
const nodes = [];
|
|
141
|
+
for (const srv of servers) {
|
|
142
|
+
const heur = matchHeuristic(srv.name);
|
|
143
|
+
let risk;
|
|
144
|
+
let source;
|
|
145
|
+
let toolCount;
|
|
146
|
+
if (heur) {
|
|
147
|
+
risk = heur;
|
|
148
|
+
source = "heuristic";
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
risk = UNKNOWN_HEURISTIC;
|
|
152
|
+
source = "unknown";
|
|
153
|
+
}
|
|
154
|
+
if (opts.empiricalProbe && srv.command && (!opts.probeOnly || opts.probeOnly.includes(srv.name))) {
|
|
155
|
+
const probe = await probeServer({
|
|
156
|
+
name: srv.name,
|
|
157
|
+
command: srv.command,
|
|
158
|
+
args: srv.args,
|
|
159
|
+
env: srv.env,
|
|
160
|
+
});
|
|
161
|
+
if (probe.reachable) {
|
|
162
|
+
risk = promoteRiskWithProbe(risk, probe);
|
|
163
|
+
source = "empirical";
|
|
164
|
+
toolCount = probe.tools.length;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
findings.push({ server: srv.name, risk, source, toolCount });
|
|
168
|
+
nodes.push({ name: srv.name, risk, source: srv.source });
|
|
169
|
+
}
|
|
170
|
+
findings.sort((a, b) => b.risk.severity - a.risk.severity);
|
|
171
|
+
const graph = buildBypassGraph(nodes);
|
|
172
|
+
const riskBudget = totalRiskBudget(nodes);
|
|
173
|
+
const withinBudget = riskBudget <= budgetCap;
|
|
174
|
+
const sources = Array.from(new Set(servers.map((s) => s.source)));
|
|
175
|
+
const summary = servers.length === 0
|
|
176
|
+
? "no MCP servers discovered — install Claude Desktop / Cursor + add at least one mcpServers entry"
|
|
177
|
+
: `${servers.length} MCP server(s) across ${sources.length} config(s); risk budget ${riskBudget}/${budgetCap}; ${graph.bypassPaths.length} bypass path(s); ${findings.filter((f) => f.risk.severity >= 0.85).length} critical finding(s).`;
|
|
178
|
+
const body = {
|
|
179
|
+
ok: withinBudget && findings.filter((f) => f.risk.severity >= 0.85).length === 0,
|
|
180
|
+
at, totalServers: servers.length, sources,
|
|
181
|
+
findings, graph, riskBudget, budgetCap, withinBudget, summary,
|
|
182
|
+
};
|
|
183
|
+
const hmac = createHmac("sha256", keyOf()).update(JSON.stringify(body)).digest("hex");
|
|
184
|
+
return { ...body, hmac };
|
|
185
|
+
}
|
|
186
|
+
export function verifyAudit(a) {
|
|
187
|
+
if (!a || typeof a.hmac !== "string")
|
|
188
|
+
return false;
|
|
189
|
+
const { hmac, ...body } = a;
|
|
190
|
+
const expected = createHmac("sha256", keyOf()).update(JSON.stringify(body)).digest("hex");
|
|
191
|
+
return expected === hmac;
|
|
192
|
+
}
|
|
193
|
+
function digestCommand(cmd, args) {
|
|
194
|
+
const blob = `${cmd ?? ""}|${(args ?? []).join("|")}`;
|
|
195
|
+
return createHmac("sha256", keyOf()).update(blob).digest("hex").slice(0, 16);
|
|
196
|
+
}
|
|
197
|
+
function snapshotPath(cwd) {
|
|
198
|
+
return join(cwd, ".mneme", "skeleton_key", "config_snapshot.json");
|
|
199
|
+
}
|
|
200
|
+
export function pinConfigSnapshot(cwd, configPaths) {
|
|
201
|
+
const servers = discoverServers(configPaths ?? defaultConfigPaths());
|
|
202
|
+
const body = {
|
|
203
|
+
at: new Date().toISOString(),
|
|
204
|
+
servers: servers.map((s) => ({
|
|
205
|
+
name: s.name,
|
|
206
|
+
commandHash: digestCommand(s.command, s.args),
|
|
207
|
+
source: s.source,
|
|
208
|
+
})),
|
|
209
|
+
};
|
|
210
|
+
const hmac = createHmac("sha256", keyOf()).update(JSON.stringify(body)).digest("hex");
|
|
211
|
+
const snap = { ...body, hmac };
|
|
212
|
+
try {
|
|
213
|
+
mkdirSync(dirname(snapshotPath(cwd)), { recursive: true });
|
|
214
|
+
writeFileSync(snapshotPath(cwd), JSON.stringify(snap, null, 2));
|
|
215
|
+
}
|
|
216
|
+
catch { /* noop */ }
|
|
217
|
+
return snap;
|
|
218
|
+
}
|
|
219
|
+
export function detectConfigDrift(cwd, configPaths) {
|
|
220
|
+
const path = snapshotPath(cwd);
|
|
221
|
+
const currentAt = new Date().toISOString();
|
|
222
|
+
if (!existsSync(path)) {
|
|
223
|
+
return {
|
|
224
|
+
ok: false, hasSnapshot: false,
|
|
225
|
+
added: [], removed: [], modified: [], currentAt,
|
|
226
|
+
hint: "no snapshot pinned — run `mneme skeleton_key pin` to lock current config",
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
let snap;
|
|
230
|
+
try {
|
|
231
|
+
snap = JSON.parse(readFileSync(path, "utf8"));
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return {
|
|
235
|
+
ok: false, hasSnapshot: false,
|
|
236
|
+
added: [], removed: [], modified: [], currentAt,
|
|
237
|
+
hint: "snapshot file unreadable / corrupted",
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const current = discoverServers(configPaths ?? defaultConfigPaths());
|
|
241
|
+
const currentMap = new Map(current.map((s) => [s.name, { commandHash: digestCommand(s.command, s.args), source: s.source }]));
|
|
242
|
+
const snapMap = new Map(snap.servers.map((s) => [s.name, s]));
|
|
243
|
+
const added = [];
|
|
244
|
+
const removed = [];
|
|
245
|
+
const modified = [];
|
|
246
|
+
for (const [name, cur] of currentMap.entries()) {
|
|
247
|
+
const old = snapMap.get(name);
|
|
248
|
+
if (!old)
|
|
249
|
+
added.push({ name, source: cur.source });
|
|
250
|
+
else if (old.commandHash !== cur.commandHash)
|
|
251
|
+
modified.push({ name, oldHash: old.commandHash, newHash: cur.commandHash });
|
|
252
|
+
}
|
|
253
|
+
for (const [name, old] of snapMap.entries()) {
|
|
254
|
+
if (!currentMap.has(name))
|
|
255
|
+
removed.push({ name, source: old.source });
|
|
256
|
+
}
|
|
257
|
+
const ok = added.length === 0 && removed.length === 0 && modified.length === 0;
|
|
258
|
+
return {
|
|
259
|
+
ok, hasSnapshot: true, added, removed, modified,
|
|
260
|
+
snapshotAt: snap.at, currentAt,
|
|
261
|
+
hint: ok
|
|
262
|
+
? "config unchanged since pin"
|
|
263
|
+
: `drift detected: ${added.length} added · ${removed.length} removed · ${modified.length} modified (re-pin with \`mneme skeleton_key pin\` after review)`,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
export function buildRecommendations(audit) {
|
|
267
|
+
const recs = [];
|
|
268
|
+
for (const f of audit.findings) {
|
|
269
|
+
if (f.risk.severity < 0.55)
|
|
270
|
+
continue;
|
|
271
|
+
recs.push({
|
|
272
|
+
server: f.server,
|
|
273
|
+
severity: f.risk.severity,
|
|
274
|
+
cwe: f.risk.cwe,
|
|
275
|
+
action: f.risk.mitigation,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
if (audit.graph.bypassPaths.length > 0) {
|
|
279
|
+
recs.push({
|
|
280
|
+
server: "BYPASS GRAPH",
|
|
281
|
+
severity: audit.graph.bypassPaths[0].weakestSeverity,
|
|
282
|
+
cwe: "CWE-269",
|
|
283
|
+
action: `${audit.graph.bypassPaths.length} bypass path(s) detected — narrow capability scope across servers; wrap with PASSPORT mediation.`,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
if (!audit.withinBudget) {
|
|
287
|
+
recs.push({
|
|
288
|
+
server: "RISK BUDGET",
|
|
289
|
+
severity: 0.80,
|
|
290
|
+
cwe: "CWE-1059",
|
|
291
|
+
action: `risk budget ${audit.riskBudget} exceeds cap ${audit.budgetCap} — remove a high-severity server OR raise the cap with explicit justification.`,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return recs;
|
|
295
|
+
}
|
|
296
|
+
/* ── Render banner ───────────────────────────────────────────────── */
|
|
297
|
+
export function renderAuditBanner(a) {
|
|
298
|
+
const lines = [
|
|
299
|
+
`🦴 SKELETON KEY · ${a.summary}`,
|
|
300
|
+
` risk budget: ${a.riskBudget}/${a.budgetCap} ${a.withinBudget ? "✓" : "✗ OVER BUDGET"}`,
|
|
301
|
+
` sources: ${a.sources.join(", ") || "(none)"}`,
|
|
302
|
+
"",
|
|
303
|
+
];
|
|
304
|
+
for (const f of a.findings.slice(0, 10)) {
|
|
305
|
+
const sym = f.risk.severity >= 0.85 ? "🚨" : f.risk.severity >= 0.65 ? "⚠ " : "·";
|
|
306
|
+
const evidence = f.source === "empirical" ? `[empirical · ${f.toolCount} tools]` : "[heuristic]";
|
|
307
|
+
lines.push(` ${sym} ${f.server.padEnd(22)} ${(f.risk.severity * 100).toFixed(0).padStart(3)}% ${f.risk.cwe} ${f.risk.riskName} ${evidence}`);
|
|
308
|
+
}
|
|
309
|
+
if (a.graph.bypassPaths.length > 0) {
|
|
310
|
+
lines.push("");
|
|
311
|
+
lines.push(` BYPASS PATHS (${a.graph.bypassPaths.length}):`);
|
|
312
|
+
for (const bp of a.graph.bypassPaths.slice(0, 5)) {
|
|
313
|
+
lines.push(` → ${bp.narrative}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return lines.join("\n");
|
|
317
|
+
}
|
|
318
|
+
export { RISK_HEURISTICS, UNKNOWN_HEURISTIC, matchHeuristic } from "./risk_heuristics.js";
|
|
319
|
+
export { buildBypassGraph, totalRiskBudget } from "./bypass_graph.js";
|
|
320
|
+
export { probeServer } from "./capability_probe.js";
|
|
321
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skeleton_key/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.60.0 — SKELETON KEY risk heuristics.
|
|
3
|
+
*
|
|
4
|
+
* Pattern-based risk scoring for MCP servers, name-only path. Used as
|
|
5
|
+
* the fast first pass; CAPABILITY PROBE upgrades the scoring with
|
|
6
|
+
* empirical evidence (real tools/list result from spawning the server).
|
|
7
|
+
*
|
|
8
|
+
* Severity scale 0..1:
|
|
9
|
+
* 0.0-0.3 → low (read-only / sandboxed)
|
|
10
|
+
* 0.3-0.6 → medium (scoped mutations)
|
|
11
|
+
* 0.6-0.85 → high (broad mutations)
|
|
12
|
+
* 0.85-1.0 → critical (arbitrary execution / unrestricted FS / DB DDL)
|
|
13
|
+
*
|
|
14
|
+
* Every entry maps to a CWE (Common Weakness Enumeration) for
|
|
15
|
+
* compliance audit-grade output.
|
|
16
|
+
*/
|
|
17
|
+
export interface RiskHeuristic {
|
|
18
|
+
/** Lowercase substring to match against server name. */
|
|
19
|
+
match: string;
|
|
20
|
+
/** Human-readable risk class. */
|
|
21
|
+
riskName: string;
|
|
22
|
+
/** 0..1 severity. */
|
|
23
|
+
severity: number;
|
|
24
|
+
/** Suggested mitigation. */
|
|
25
|
+
mitigation: string;
|
|
26
|
+
/** CWE id for compliance mapping. */
|
|
27
|
+
cwe: string;
|
|
28
|
+
/** Capability tags exposed (used by bypass graph). */
|
|
29
|
+
capabilities: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Ordered most-specific → least-specific. First match wins per server.
|
|
33
|
+
* Each entry curated from MCP ecosystem observation (2026-05).
|
|
34
|
+
*/
|
|
35
|
+
export declare const RISK_HEURISTICS: RiskHeuristic[];
|
|
36
|
+
/**
|
|
37
|
+
* Match a server name against heuristics. Returns the highest-severity
|
|
38
|
+
* matching heuristic, or null if no match (= unknown → conservative HIGH).
|
|
39
|
+
*/
|
|
40
|
+
export declare function matchHeuristic(serverName: string): RiskHeuristic | null;
|
|
41
|
+
/**
|
|
42
|
+
* Unknown / unmatched server. Conservative default: treat as medium risk
|
|
43
|
+
* with hint to run capability probe for exact assessment.
|
|
44
|
+
*/
|
|
45
|
+
export declare const UNKNOWN_HEURISTIC: RiskHeuristic;
|
|
46
|
+
//# sourceMappingURL=risk_heuristics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk_heuristics.d.ts","sourceRoot":"","sources":["../../src/skeleton_key/risk_heuristics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAiK1C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAKvE;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,aAO/B,CAAC"}
|