@permission-protocol/mcp-guard 0.1.0 → 0.2.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/CHANGELOG.md +45 -0
- package/LICENSE +21 -0
- package/README.md +101 -59
- package/SECURITY.md +40 -0
- package/dist/src/approval-server.d.ts +69 -3
- package/dist/src/approval-server.js +345 -86
- package/dist/src/approval-server.js.map +1 -1
- package/dist/src/approval-ui.d.ts +5 -0
- package/dist/src/approval-ui.js +120 -81
- package/dist/src/approval-ui.js.map +1 -1
- package/dist/src/classify.d.ts +29 -0
- package/dist/src/classify.js +107 -0
- package/dist/src/classify.js.map +1 -0
- package/dist/src/cli.js +49 -12
- package/dist/src/cli.js.map +1 -1
- package/dist/src/config.d.ts +21 -1
- package/dist/src/config.js +92 -5
- package/dist/src/config.js.map +1 -1
- package/dist/src/enforcement/index.d.ts +12 -0
- package/dist/src/enforcement/index.js +53 -0
- package/dist/src/enforcement/index.js.map +1 -0
- package/dist/src/enforcement/policy.d.ts +29 -0
- package/dist/src/enforcement/policy.js +60 -0
- package/dist/src/enforcement/policy.js.map +1 -0
- package/dist/src/enforcement/types.d.ts +19 -0
- package/dist/src/enforcement/types.js +3 -0
- package/dist/src/enforcement/types.js.map +1 -0
- package/dist/src/enforcement/verifier.d.ts +4 -0
- package/dist/src/enforcement/verifier.js +110 -0
- package/dist/src/enforcement/verifier.js.map +1 -0
- package/dist/src/engine.d.ts +11 -2
- package/dist/src/engine.js +20 -14
- package/dist/src/engine.js.map +1 -1
- package/dist/src/frame.d.ts +67 -0
- package/dist/src/frame.js +113 -0
- package/dist/src/frame.js.map +1 -0
- package/dist/src/pending.d.ts +108 -12
- package/dist/src/pending.js +174 -24
- package/dist/src/pending.js.map +1 -1
- package/dist/src/proxy.d.ts +29 -2
- package/dist/src/proxy.js +274 -105
- package/dist/src/proxy.js.map +1 -1
- package/dist/src/receipt-verify.d.ts +36 -0
- package/dist/src/receipt-verify.js +88 -0
- package/dist/src/receipt-verify.js.map +1 -0
- package/dist/src/receipt.d.ts +81 -7
- package/dist/src/receipt.js +100 -17
- package/dist/src/receipt.js.map +1 -1
- package/dist/src/signer.d.ts +38 -0
- package/dist/src/signer.js +112 -0
- package/dist/src/signer.js.map +1 -0
- package/dist/src/verify-cli.d.ts +1 -0
- package/dist/src/verify-cli.js +133 -0
- package/dist/src/verify-cli.js.map +1 -0
- package/dist/src/verify-core.d.ts +22 -0
- package/dist/src/verify-core.js +50 -0
- package/dist/src/verify-core.js.map +1 -0
- package/dist/src/webhook.d.ts +35 -0
- package/dist/src/webhook.js +57 -0
- package/dist/src/webhook.js.map +1 -0
- package/example/test.sh +5 -7
- package/package.json +33 -7
- package/templates/github-actions/receipt-gate.yml +64 -0
- package/assets/demo.gif +0 -0
- package/demo/_demo-scenario.sh +0 -43
- package/dist/src/tests/config.test.d.ts +0 -1
- package/dist/src/tests/config.test.js +0 -63
- package/dist/src/tests/config.test.js.map +0 -1
- package/dist/src/tests/engine.test.d.ts +0 -1
- package/dist/src/tests/engine.test.js +0 -46
- package/dist/src/tests/engine.test.js.map +0 -1
- package/dist/src/tests/receipt.test.d.ts +0 -1
- package/dist/src/tests/receipt.test.js +0 -44
- package/dist/src/tests/receipt.test.js.map +0 -1
- package/docs/index.html +0 -771
- package/permission-protocol-mcp-guard-0.1.0.tgz +0 -0
- package/src/approval-server.ts +0 -136
- package/src/approval-ui.ts +0 -154
- package/src/cli.ts +0 -84
- package/src/config.ts +0 -68
- package/src/engine.ts +0 -31
- package/src/pending.ts +0 -65
- package/src/proxy.ts +0 -173
- package/src/receipt.ts +0 -52
- package/src/tests/config.test.ts +0 -61
- package/src/tests/engine.test.ts +0 -47
- package/src/tests/receipt.test.ts +0 -44
- package/tsconfig.json +0 -16
package/dist/src/proxy.js
CHANGED
|
@@ -1,25 +1,116 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.derivePreview = derivePreview;
|
|
4
|
+
exports.buildEnrichment = buildEnrichment;
|
|
5
|
+
exports.deriveScope = deriveScope;
|
|
3
6
|
exports.startProxy = startProxy;
|
|
4
7
|
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
5
9
|
const node_readline_1 = require("node:readline");
|
|
10
|
+
const config_js_1 = require("./config.js");
|
|
6
11
|
const engine_js_1 = require("./engine.js");
|
|
7
12
|
const receipt_js_1 = require("./receipt.js");
|
|
13
|
+
const receipt_verify_js_1 = require("./receipt-verify.js");
|
|
14
|
+
const signer_js_1 = require("./signer.js");
|
|
15
|
+
const verify_core_js_1 = require("./verify-core.js");
|
|
8
16
|
const pending_js_1 = require("./pending.js");
|
|
9
17
|
const approval_server_js_1 = require("./approval-server.js");
|
|
10
|
-
|
|
18
|
+
const frame_js_1 = require("./frame.js");
|
|
19
|
+
/**
|
|
20
|
+
* Derive a one-line summary + the literal artifact preview from the tool name and args,
|
|
21
|
+
* so the console can render a human-readable card. For capped spends the amount shown is
|
|
22
|
+
* the argument the rule caps (`amountArg`), the same one the classifier read.
|
|
23
|
+
*/
|
|
24
|
+
function derivePreview(toolName, toolArgs, amountArg) {
|
|
25
|
+
const args = (toolArgs ?? {});
|
|
26
|
+
const str = (v) => (v === undefined || v === null ? '' : String(v));
|
|
27
|
+
switch (toolName) {
|
|
28
|
+
case 'send_email': {
|
|
29
|
+
const to = str(args.to ?? args.recipient);
|
|
30
|
+
const subject = str(args.subject);
|
|
31
|
+
const body = str(args.body ?? args.text ?? args.message);
|
|
32
|
+
const summary = `Send email${to ? ` to ${to}` : ''}${subject ? `: ${subject}` : ''}`.trim();
|
|
33
|
+
return { summary, args_preview: body || subject || JSON.stringify(args) };
|
|
34
|
+
}
|
|
35
|
+
case 'post_x':
|
|
36
|
+
case 'post_tweet': {
|
|
37
|
+
const text = str(args.text ?? args.body ?? args.message ?? args.content);
|
|
38
|
+
return { summary: 'Post to X', args_preview: text || JSON.stringify(args) };
|
|
39
|
+
}
|
|
40
|
+
case 'spend': {
|
|
41
|
+
const amount = amountArg ? args[amountArg] : (args.amount_usd ?? args.amount);
|
|
42
|
+
const payee = str(args.payee ?? args.to ?? args.recipient ?? args.vendor);
|
|
43
|
+
const amountStr = amount !== undefined ? `$${amount}` : '';
|
|
44
|
+
const preview = `${amountStr}${payee ? ` → ${payee}` : ''}`.trim();
|
|
45
|
+
return { summary: `Spend ${preview || JSON.stringify(args)}`, args_preview: preview || JSON.stringify(args) };
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
return { summary: `Call ${toolName}`, args_preview: JSON.stringify(args) };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Build the enrichment record for the queue from a classified Decision + args. */
|
|
52
|
+
function buildEnrichment(decision, toolName, toolArgs, rule) {
|
|
53
|
+
const { summary, args_preview } = derivePreview(toolName, toolArgs, rule?.amount_arg);
|
|
54
|
+
return {
|
|
55
|
+
lane: decision.lane ?? 'decide',
|
|
56
|
+
reversibility: decision.reversibility ?? 'irreversible',
|
|
57
|
+
...(decision.countdown_seconds !== undefined ? { countdown_seconds: decision.countdown_seconds } : {}),
|
|
58
|
+
...(decision.confidence !== undefined ? { confidence: decision.confidence } : {}),
|
|
59
|
+
summary,
|
|
60
|
+
args_preview,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Derive a receipt scope binding from the tool + args, for the code/infra tools the
|
|
65
|
+
* offline receipt gate verifies:
|
|
66
|
+
* - merge_pr -> `github:merge`, ref `refs/pull/<n>/merge`
|
|
67
|
+
* - run_sql_migration -> `sql:migrate:<env>`
|
|
68
|
+
* - deploy -> `deploy:<env>`
|
|
69
|
+
* Other tools carry no scope.
|
|
70
|
+
*/
|
|
71
|
+
function deriveScope(toolName, toolArgs) {
|
|
72
|
+
const args = (toolArgs ?? {});
|
|
73
|
+
const str = (v) => (v === undefined || v === null ? undefined : String(v));
|
|
74
|
+
switch (toolName) {
|
|
75
|
+
case 'merge_pr': {
|
|
76
|
+
const prNumber = str(args.pr_number ?? args.pr ?? args.number);
|
|
77
|
+
return {
|
|
78
|
+
scope: 'github:merge',
|
|
79
|
+
scope_ref: prNumber !== undefined ? `refs/pull/${prNumber}/merge` : undefined,
|
|
80
|
+
scope_sha: str(args.scope_sha ?? args.head_sha ?? args.sha),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
case 'run_sql_migration':
|
|
84
|
+
return {
|
|
85
|
+
scope: `sql:migrate:${str(args.env ?? args.environment) ?? 'unknown'}`,
|
|
86
|
+
scope_ref: str(args.scope_ref ?? args.migration ?? args.migration_id),
|
|
87
|
+
scope_sha: str(args.scope_sha ?? args.sha),
|
|
88
|
+
};
|
|
89
|
+
case 'deploy':
|
|
90
|
+
return {
|
|
91
|
+
scope: `deploy:${str(args.env ?? args.environment) ?? 'unknown'}`,
|
|
92
|
+
scope_ref: str(args.scope_ref ?? args.ref),
|
|
93
|
+
scope_sha: str(args.scope_sha ?? args.sha),
|
|
94
|
+
};
|
|
95
|
+
default:
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function startProxy(config, agentId, serverCommand, opts = {}) {
|
|
11
100
|
if (serverCommand.length === 0) {
|
|
12
101
|
process.stderr.write('[mcp-guard] Error: no server command provided after --\n');
|
|
13
102
|
process.exit(1);
|
|
14
103
|
}
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
104
|
+
// Load the signing key up front: a missing or exposed key stops the guard here
|
|
105
|
+
// instead of failing open later.
|
|
106
|
+
const pinnedKeys = { [(0, signer_js_1.currentKeyId)()]: (0, signer_js_1.getPublicKeyPem)() };
|
|
107
|
+
const replayCache = new verify_core_js_1.ReplayCache();
|
|
108
|
+
const targetServer = serverCommand.slice(0, 2).map((p) => (0, node_path_1.basename)(p)).join(' ');
|
|
109
|
+
const approvalEnabled = opts.approvalPort !== undefined;
|
|
110
|
+
// The server (and anything the agent can make it echo) never sees the guard's own
|
|
111
|
+
// secrets: approval token, webhook secret, receipt token, key location.
|
|
112
|
+
const childEnv = Object.fromEntries(Object.entries(process.env).filter(([k]) => !k.startsWith('PP_')));
|
|
113
|
+
const child = (0, node_child_process_1.spawn)(serverCommand[0], serverCommand.slice(1), { stdio: ['pipe', 'pipe', 'inherit'], env: childEnv });
|
|
23
114
|
child.on('error', (err) => {
|
|
24
115
|
process.stderr.write(`[mcp-guard] Failed to start server: ${err.message}\n`);
|
|
25
116
|
process.exit(1);
|
|
@@ -28,119 +119,197 @@ function startProxy(config, agentId, serverCommand, approvalPort) {
|
|
|
28
119
|
process.stderr.write(`[mcp-guard] Server exited with code ${code}\n`);
|
|
29
120
|
process.exit(code ?? 1);
|
|
30
121
|
});
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
122
|
+
const toClient = (line) => { process.stdout.write(line + '\n'); };
|
|
123
|
+
const toServer = (msg) => { child.stdin.write(JSON.stringify(msg) + '\n'); };
|
|
124
|
+
// Server → client traffic is passed through unchanged.
|
|
125
|
+
(0, node_readline_1.createInterface)({ input: child.stdout }).on('line', toClient);
|
|
126
|
+
function record(method, tool, args, decision, approval, actor) {
|
|
127
|
+
const receipt = (0, receipt_js_1.issueReceipt)({
|
|
128
|
+
method,
|
|
129
|
+
tool,
|
|
130
|
+
args,
|
|
131
|
+
decision,
|
|
132
|
+
approval,
|
|
133
|
+
actor,
|
|
134
|
+
mode: config.mode,
|
|
135
|
+
policy_sha256: config.policy_sha256,
|
|
136
|
+
ttl_seconds: config.receipt_ttl_seconds,
|
|
137
|
+
target_server: targetServer,
|
|
138
|
+
scope: tool ? deriveScope(tool, args) : undefined,
|
|
139
|
+
});
|
|
140
|
+
(0, receipt_js_1.emitReceipt)(receipt);
|
|
141
|
+
if (approvalEnabled)
|
|
142
|
+
(0, approval_server_js_1.pushReceipt)(receipt);
|
|
143
|
+
return receipt;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The single release path for held requests (manual approve and countdown): issue the
|
|
147
|
+
* signed receipt, verify it against the pinned key, and only then forward.
|
|
148
|
+
*/
|
|
149
|
+
function release(action, approval) {
|
|
150
|
+
const tool = action.method === config_js_1.TOOLS_CALL ? action.tool_name : null;
|
|
151
|
+
const decision = {
|
|
152
|
+
decision: 'allowed',
|
|
153
|
+
rule_id: action.rule_id,
|
|
154
|
+
reason: `Released by ${approval.kind} "${approval.id}" (${approval.via})`,
|
|
155
|
+
};
|
|
156
|
+
const receipt = record(action.method, tool, action.tool_args, decision, approval, action.agent_id);
|
|
157
|
+
const check = (0, receipt_verify_js_1.verifyReceipt)(receipt, pinnedKeys, { replayCache, allowPolicyApproval: true });
|
|
158
|
+
if (!check.valid) {
|
|
159
|
+
action.resolve((0, frame_js_1.errorLine)(action.jsonrpcId, frame_js_1.RELEASE_FAILED, `Release refused: ${check.reasons.join(' ')}`));
|
|
160
|
+
throw new Error(`release refused for ${action.id}: ${check.reasons.join(' ')}`);
|
|
161
|
+
}
|
|
162
|
+
action.receipt_id = receipt.envelope.receipt_id;
|
|
163
|
+
child.stdin.write(action.forwardLine + '\n');
|
|
164
|
+
return receipt;
|
|
165
|
+
}
|
|
166
|
+
if (approvalEnabled) {
|
|
167
|
+
const server = (0, approval_server_js_1.startApprovalServer)({
|
|
168
|
+
port: opts.approvalPort,
|
|
169
|
+
operator: opts.operator,
|
|
170
|
+
hooks: { release },
|
|
171
|
+
receiptTtlSeconds: config.receipt_ttl_seconds,
|
|
172
|
+
policySha256: config.policy_sha256,
|
|
173
|
+
});
|
|
174
|
+
server.ready.catch((err) => {
|
|
175
|
+
process.stderr.write(`[mcp-guard] Approval server failed to start: ${err.message}\n`);
|
|
176
|
+
process.exit(1);
|
|
177
|
+
});
|
|
178
|
+
(0, pending_js_1.setAutoReleaseHandler)((action) => {
|
|
179
|
+
process.stderr.write(`[mcp-guard] Auto-released (countdown) "${action.tool_name}" (${action.id})\n`);
|
|
180
|
+
try {
|
|
181
|
+
release(action, { kind: 'policy', id: action.rule_id ?? 'default_action', via: 'countdown' });
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
process.stderr.write(`[mcp-guard] ${err.message}\n`);
|
|
185
|
+
}
|
|
186
|
+
(0, approval_server_js_1.notifyQueueChange)();
|
|
187
|
+
});
|
|
188
|
+
(0, pending_js_1.setExpireHandler)((action) => {
|
|
189
|
+
process.stderr.write(`[mcp-guard] Expired without a decision: "${action.tool_name}" (${action.id})\n`);
|
|
190
|
+
if (action.kind === 'held')
|
|
191
|
+
action.resolve((0, frame_js_1.errorLine)(action.jsonrpcId, frame_js_1.EXPIRED, 'Approval request expired without a decision'));
|
|
192
|
+
(0, approval_server_js_1.notifyQueueChange)();
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function gate(msg, isRequest) {
|
|
196
|
+
const id = msg.id ?? null;
|
|
197
|
+
const reply = (line) => { if (isRequest)
|
|
198
|
+
toClient(line); };
|
|
199
|
+
let tool = null;
|
|
200
|
+
let args;
|
|
201
|
+
if (msg.method === config_js_1.TOOLS_CALL) {
|
|
202
|
+
const target = (0, frame_js_1.toolCallTarget)(msg.params);
|
|
203
|
+
if ('error' in target) {
|
|
204
|
+
reply((0, frame_js_1.errorLine)(id, frame_js_1.INVALID_PARAMS, target.error));
|
|
44
205
|
return;
|
|
45
206
|
}
|
|
207
|
+
tool = target.name;
|
|
208
|
+
args = target.args;
|
|
46
209
|
}
|
|
47
|
-
|
|
48
|
-
|
|
210
|
+
const decision = (0, engine_js_1.evaluate)(tool, args, config, msg.method);
|
|
211
|
+
const rule = decision.rule_id ? config.rules.find((r) => r.id === decision.rule_id) ?? null : null;
|
|
212
|
+
const forward = (0, frame_js_1.stripAgentMetadata)(msg);
|
|
213
|
+
// What the server will act on: tool arguments for tools/call, the params otherwise.
|
|
214
|
+
// This is what the approver sees and what the receipt hashes.
|
|
215
|
+
const forwardArgs = tool
|
|
216
|
+
? forward.params.arguments
|
|
217
|
+
: forward.params === undefined ? undefined
|
|
218
|
+
: Array.isArray(forward.params) ? { params: forward.params }
|
|
219
|
+
: forward.params;
|
|
220
|
+
const label = tool ?? msg.method;
|
|
221
|
+
const policyApproval = decision.decision === 'allowed'
|
|
222
|
+
? { kind: 'policy', id: decision.rule_id ?? 'default_action', via: decision.lane === 'verify' ? 'standing_rule' : 'rule' }
|
|
223
|
+
: null;
|
|
224
|
+
const receipt = record(msg.method, tool, forwardArgs, decision, policyApproval, agentId);
|
|
225
|
+
if (!isRequest) {
|
|
226
|
+
// A notification gets no response, so it can neither be held nor told it was blocked.
|
|
227
|
+
if (decision.decision === 'allowed' || config.mode === 'observe')
|
|
228
|
+
toServer(forward);
|
|
229
|
+
else
|
|
230
|
+
process.stderr.write(`[mcp-guard] Dropped ${decision.decision} notification "${label}"\n`);
|
|
231
|
+
return;
|
|
49
232
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
233
|
+
if (config.mode === 'observe') {
|
|
234
|
+
if (decision.decision !== 'allowed') {
|
|
235
|
+
process.stderr.write(`[mcp-guard] OBSERVE: would ${decision.decision === 'blocked' ? 'block' : 'hold'} "${label}" but forwarding (observe mode)\n`);
|
|
236
|
+
}
|
|
237
|
+
toServer(forward);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (decision.decision === 'allowed') {
|
|
241
|
+
toServer(forward);
|
|
242
|
+
if (approvalEnabled && decision.lane === 'verify') {
|
|
243
|
+
const surfaced = (0, pending_js_1.surfaceActed)({
|
|
244
|
+
method: msg.method,
|
|
245
|
+
toolName: label,
|
|
246
|
+
toolArgs: forwardArgs,
|
|
247
|
+
agentId,
|
|
248
|
+
ruleId: decision.rule_id,
|
|
249
|
+
enrichment: buildEnrichment(decision, label, forwardArgs, rule),
|
|
250
|
+
receiptId: receipt.envelope.receipt_id,
|
|
251
|
+
ttlSeconds: config.approval_ttl_seconds,
|
|
62
252
|
});
|
|
253
|
+
(0, approval_server_js_1.notifyQueueChange)();
|
|
254
|
+
process.stderr.write(`[mcp-guard] Surfaced acted "${label}" in Verify (${surfaced.id})\n`);
|
|
63
255
|
}
|
|
64
|
-
|
|
65
|
-
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (decision.decision === 'blocked') {
|
|
259
|
+
toClient((0, frame_js_1.errorLine)(id, frame_js_1.BLOCKED, `Blocked: ${decision.reason}`));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
// held_for_approval
|
|
263
|
+
if (!approvalEnabled) {
|
|
264
|
+
toClient((0, frame_js_1.errorLine)(id, frame_js_1.HELD, `Held for approval: ${decision.reason}`));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const pending = (0, pending_js_1.addPending)({
|
|
268
|
+
method: msg.method,
|
|
269
|
+
toolName: label,
|
|
270
|
+
toolArgs: forwardArgs,
|
|
271
|
+
agentId,
|
|
272
|
+
ruleId: decision.rule_id,
|
|
273
|
+
forwardLine: JSON.stringify(forward),
|
|
274
|
+
jsonrpcId: id,
|
|
275
|
+
resolve: toClient,
|
|
276
|
+
enrichment: buildEnrichment(decision, label, forwardArgs, rule),
|
|
277
|
+
ttlSeconds: config.approval_ttl_seconds,
|
|
278
|
+
...(tool ? deriveScope(tool, forwardArgs) : {}),
|
|
66
279
|
});
|
|
280
|
+
(0, approval_server_js_1.notifyQueueChange)();
|
|
281
|
+
process.stderr.write(`[mcp-guard] Held "${label}" for approval (${pending.id})\n`);
|
|
67
282
|
}
|
|
68
|
-
//
|
|
283
|
+
// Client → server: parse, gate, and forward only what was evaluated.
|
|
69
284
|
const stdinRL = (0, node_readline_1.createInterface)({ input: process.stdin });
|
|
70
285
|
stdinRL.on('line', (line) => {
|
|
71
286
|
if (!line.trim())
|
|
72
287
|
return;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (decision.decision !== 'allowed') {
|
|
94
|
-
process.stderr.write(`[mcp-guard] OBSERVE: would ${decision.decision === 'blocked' ? 'block' : 'hold'} "${toolName}" but forwarding (observe mode)\n`);
|
|
95
|
-
}
|
|
96
|
-
child.stdin.write(line + '\n');
|
|
97
|
-
}
|
|
98
|
-
else if (decision.decision === 'allowed') {
|
|
99
|
-
child.stdin.write(line + '\n');
|
|
100
|
-
}
|
|
101
|
-
else if (decision.decision === 'blocked') {
|
|
102
|
-
const errResp = {
|
|
103
|
-
jsonrpc: '2.0',
|
|
104
|
-
id: msg.id ?? null,
|
|
105
|
-
error: {
|
|
106
|
-
code: -32001,
|
|
107
|
-
message: `Blocked: ${decision.reason}`,
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
process.stdout.write(JSON.stringify(errResp) + '\n');
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
// held_for_approval
|
|
114
|
-
if (approvalEnabled) {
|
|
115
|
-
// Hold the response — add to pending queue
|
|
116
|
-
const pending = (0, pending_js_1.addPending)(toolName, toolArgs, agentId, decision.rule_id ?? 'unknown', line, msg.id ?? null, (responseLine) => {
|
|
117
|
-
process.stdout.write(responseLine + '\n');
|
|
118
|
-
});
|
|
119
|
-
process.stderr.write(`[mcp-guard] Held "${toolName}" for approval (${pending.id}) — approve at UI\n`);
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
// No approval server — return error immediately (original behavior)
|
|
123
|
-
const errResp = {
|
|
124
|
-
jsonrpc: '2.0',
|
|
125
|
-
id: msg.id ?? null,
|
|
126
|
-
error: {
|
|
127
|
-
code: -32002,
|
|
128
|
-
message: `Held for approval: ${decision.reason}`,
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
process.stdout.write(JSON.stringify(errResp) + '\n');
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
// Pass through all non-tools/call methods
|
|
137
|
-
child.stdin.write(line + '\n');
|
|
288
|
+
const frame = (0, frame_js_1.parseFrame)(line);
|
|
289
|
+
switch (frame.kind) {
|
|
290
|
+
case 'invalid':
|
|
291
|
+
toClient((0, frame_js_1.errorLine)(frame.id, frame.code, frame.message));
|
|
292
|
+
return;
|
|
293
|
+
case 'response':
|
|
294
|
+
toServer(frame.msg);
|
|
295
|
+
return;
|
|
296
|
+
case 'notification':
|
|
297
|
+
if ((0, frame_js_1.isPassthrough)(frame.msg.method))
|
|
298
|
+
toServer(frame.msg);
|
|
299
|
+
else
|
|
300
|
+
gate(frame.msg, false);
|
|
301
|
+
return;
|
|
302
|
+
case 'request':
|
|
303
|
+
if ((0, frame_js_1.isPassthrough)(frame.msg.method))
|
|
304
|
+
toServer(frame.msg);
|
|
305
|
+
else
|
|
306
|
+
gate(frame.msg, true);
|
|
307
|
+
return;
|
|
138
308
|
}
|
|
139
309
|
});
|
|
140
310
|
stdinRL.on('close', () => {
|
|
141
311
|
child.stdin.end();
|
|
142
312
|
});
|
|
143
|
-
// Handle signals gracefully
|
|
144
313
|
process.on('SIGINT', () => child.kill('SIGINT'));
|
|
145
314
|
process.on('SIGTERM', () => child.kill('SIGTERM'));
|
|
146
315
|
}
|
package/dist/src/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Receipt } from './receipt.js';
|
|
2
|
+
import { type PinnedKeys, type ReplayCache } from './verify-core.js';
|
|
3
|
+
/**
|
|
4
|
+
* OFFLINE receipt verifier — the deploy-gate side of "the receipt is the bridge".
|
|
5
|
+
*
|
|
6
|
+
* Given a receipt and the PINNED public keys, decide with no network whether the
|
|
7
|
+
* receipt authorizes an action. Checks:
|
|
8
|
+
* 1. receipt v2 with a well-formed envelope,
|
|
9
|
+
* 2. Ed25519 signature over the canonical envelope, by a pinned key,
|
|
10
|
+
* 3. decision is `allowed` with a recorded approval,
|
|
11
|
+
* 4. not expired (expires_at is required),
|
|
12
|
+
* 5. a scoped receipt was approved by a human (unless the caller allows policy approval),
|
|
13
|
+
* 6. (optional) scope / scope_ref / scope_sha exactly match the gate's expectation,
|
|
14
|
+
* 7. (optional) its nonce has not been used before.
|
|
15
|
+
*
|
|
16
|
+
* Fail-closed: any failed check yields `valid: false` with reasons. Only the envelope is
|
|
17
|
+
* read; the unsigned `display` block is ignored.
|
|
18
|
+
*/
|
|
19
|
+
export interface ExpectedScope {
|
|
20
|
+
scope?: string;
|
|
21
|
+
scope_ref?: string;
|
|
22
|
+
scope_sha?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface VerifyOptions {
|
|
25
|
+
expected?: ExpectedScope;
|
|
26
|
+
now?: Date;
|
|
27
|
+
/** Accept policy approvals (countdown, standing rule) on scoped receipts. Default false. */
|
|
28
|
+
allowPolicyApproval?: boolean;
|
|
29
|
+
/** When given, the receipt's nonce is consumed; a second use fails. */
|
|
30
|
+
replayCache?: ReplayCache;
|
|
31
|
+
}
|
|
32
|
+
export interface VerifyResult {
|
|
33
|
+
valid: boolean;
|
|
34
|
+
reasons: string[];
|
|
35
|
+
}
|
|
36
|
+
export declare function verifyReceipt(receipt: Receipt, keys: PinnedKeys, opts?: VerifyOptions): VerifyResult;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verifyReceipt = verifyReceipt;
|
|
4
|
+
const receipt_js_1 = require("./receipt.js");
|
|
5
|
+
const verify_core_js_1 = require("./verify-core.js");
|
|
6
|
+
const STRING_FIELDS = [
|
|
7
|
+
'receipt_id', 'method', 'args_sha256', 'decision', 'actor', 'policy_sha256', 'mode', 'issued_at', 'expires_at', 'nonce', 'key_id',
|
|
8
|
+
];
|
|
9
|
+
function envelopeShapeErrors(e) {
|
|
10
|
+
const errs = [];
|
|
11
|
+
if (!e || typeof e !== 'object' || Array.isArray(e))
|
|
12
|
+
return ['envelope missing'];
|
|
13
|
+
for (const f of STRING_FIELDS)
|
|
14
|
+
if (typeof e[f] !== 'string' || !e[f])
|
|
15
|
+
errs.push(`${f} missing`);
|
|
16
|
+
if (e.tool !== null && typeof e.tool !== 'string')
|
|
17
|
+
errs.push('tool invalid');
|
|
18
|
+
if (e.rule_id !== null && typeof e.rule_id !== 'string')
|
|
19
|
+
errs.push('rule_id invalid');
|
|
20
|
+
if (e.scope !== null) {
|
|
21
|
+
const s = e.scope;
|
|
22
|
+
if (!s || typeof s !== 'object' || typeof s.scope !== 'string'
|
|
23
|
+
|| (s.ref !== null && typeof s.ref !== 'string') || (s.sha !== null && typeof s.sha !== 'string')) {
|
|
24
|
+
errs.push('scope invalid');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (e.approval !== null) {
|
|
28
|
+
const a = e.approval;
|
|
29
|
+
if (!a || typeof a !== 'object' || (a.kind !== 'human' && a.kind !== 'policy') || typeof a.id !== 'string' || typeof a.via !== 'string') {
|
|
30
|
+
errs.push('approval invalid');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return errs;
|
|
34
|
+
}
|
|
35
|
+
function verifyReceipt(receipt, keys, opts = {}) {
|
|
36
|
+
const reasons = [];
|
|
37
|
+
const now = opts.now ?? new Date();
|
|
38
|
+
const e = receipt?.envelope;
|
|
39
|
+
if (!e || e.v !== receipt_js_1.RECEIPT_VERSION) {
|
|
40
|
+
return { valid: false, reasons: [`PP_UNSUPPORTED_VERSION: expected receipt v${receipt_js_1.RECEIPT_VERSION}.`] };
|
|
41
|
+
}
|
|
42
|
+
const shape = envelopeShapeErrors(e);
|
|
43
|
+
if (shape.length) {
|
|
44
|
+
return { valid: false, reasons: [`PP_MALFORMED_RECEIPT: ${shape.join(', ')}.`] };
|
|
45
|
+
}
|
|
46
|
+
// Signature over the canonical envelope, by a pinned key that the envelope also names.
|
|
47
|
+
const sig = receipt.signature;
|
|
48
|
+
if (!sig || sig.alg !== 'ed25519' || sig.key_id !== e.key_id) {
|
|
49
|
+
reasons.push('PP_INVALID_SIGNATURE: signature block missing, not Ed25519, or key_id differs from the envelope.');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const err = (0, verify_core_js_1.verifyDetached)((0, receipt_js_1.signingBytes)(e), sig.value, e.key_id, keys);
|
|
53
|
+
if (err)
|
|
54
|
+
reasons.push(`PP_INVALID_SIGNATURE: ${err}.`);
|
|
55
|
+
}
|
|
56
|
+
if (e.decision !== 'allowed' || !e.approval) {
|
|
57
|
+
reasons.push(`PP_NOT_AUTHORIZED: decision is "${e.decision}"${e.approval ? '' : ' with no approval'}.`);
|
|
58
|
+
}
|
|
59
|
+
const issued = Date.parse(e.issued_at);
|
|
60
|
+
const expires = Date.parse(e.expires_at);
|
|
61
|
+
if (Number.isNaN(issued) || Number.isNaN(expires) || expires <= issued) {
|
|
62
|
+
reasons.push('PP_EXPIRED: issued_at / expires_at invalid.');
|
|
63
|
+
}
|
|
64
|
+
else if (expires <= now.getTime()) {
|
|
65
|
+
reasons.push(`PP_EXPIRED: receipt expired at ${new Date(expires).toISOString()} (now ${now.toISOString()}).`);
|
|
66
|
+
}
|
|
67
|
+
if (e.scope && e.approval && e.approval.kind !== 'human' && !opts.allowPolicyApproval) {
|
|
68
|
+
reasons.push(`PP_APPROVAL_NOT_HUMAN: scoped action was authorized by ${e.approval.kind} "${e.approval.id}" (${e.approval.via}), not a human.`);
|
|
69
|
+
}
|
|
70
|
+
if (opts.expected) {
|
|
71
|
+
const actual = {
|
|
72
|
+
scope: e.scope?.scope ?? null,
|
|
73
|
+
scope_ref: e.scope?.ref ?? null,
|
|
74
|
+
scope_sha: e.scope?.sha ?? null,
|
|
75
|
+
};
|
|
76
|
+
for (const field of ['scope', 'scope_ref', 'scope_sha']) {
|
|
77
|
+
const want = opts.expected[field];
|
|
78
|
+
if (want !== undefined && actual[field] !== want) {
|
|
79
|
+
reasons.push(`PP_SCOPE_MISMATCH: expected ${field}="${want}" but receipt has ${field}="${actual[field] ?? ''}".`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (reasons.length === 0 && opts.replayCache && !opts.replayCache.use(`${e.receipt_id}:${e.nonce}`)) {
|
|
84
|
+
reasons.push('PP_REPLAYED: this receipt has already been used.');
|
|
85
|
+
}
|
|
86
|
+
return { valid: reasons.length === 0, reasons };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=receipt-verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt-verify.js","sourceRoot":"","sources":["../../src/receipt-verify.ts"],"names":[],"mappings":"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"}
|