fullcourtdefense-cli 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/hook.js +24 -32
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/commands/hook.js
CHANGED
|
@@ -206,11 +206,6 @@ function sessionId(p) {
|
|
|
206
206
|
return fromPayload;
|
|
207
207
|
return `cursor-${os.hostname()}`;
|
|
208
208
|
}
|
|
209
|
-
function emit(decision, blocked) {
|
|
210
|
-
process.stdout.write(JSON.stringify(decision));
|
|
211
|
-
// Exit 2 is the universal "block" signal across all hook events.
|
|
212
|
-
process.exit(blocked ? 2 : 0);
|
|
213
|
-
}
|
|
214
209
|
async function hookCommand(args, config) {
|
|
215
210
|
const shadow = args.shadow === 'true';
|
|
216
211
|
const failClosed = args.failClosed === 'true';
|
|
@@ -236,15 +231,29 @@ async function hookCommand(args, config) {
|
|
|
236
231
|
}
|
|
237
232
|
const event = inferEvent(args.event, payload);
|
|
238
233
|
const text = extractText(event, payload).trim();
|
|
234
|
+
// Emit the verdict in the shape Cursor expects for THIS event, then exit.
|
|
235
|
+
// beforeSubmitPrompt blocks via { continue: false }; the execution hooks
|
|
236
|
+
// (shell/mcp/read) block via { permission: "deny" }. Exit 2 reinforces it.
|
|
237
|
+
const respond = (blocked, userMsg, agentMsg) => {
|
|
238
|
+
const decision = event === 'prompt'
|
|
239
|
+
? (blocked ? { continue: false } : { continue: true })
|
|
240
|
+
: { permission: blocked ? 'deny' : 'allow' };
|
|
241
|
+
if (userMsg)
|
|
242
|
+
decision.user_message = userMsg;
|
|
243
|
+
if (agentMsg)
|
|
244
|
+
decision.agent_message = agentMsg;
|
|
245
|
+
process.stdout.write(JSON.stringify(decision));
|
|
246
|
+
// ALWAYS exit 0 so Cursor uses our JSON verdict. Exit 2 is interpreted as
|
|
247
|
+
// `permission: "deny"`, which beforeSubmitPrompt ignores (it uses `continue`),
|
|
248
|
+
// so exiting 2 would silently let blocked prompts through.
|
|
249
|
+
process.exit(0);
|
|
250
|
+
};
|
|
239
251
|
// Nothing to scan, or no Shield configured → allow (fail-open by design here:
|
|
240
252
|
// a misconfigured machine must not brick the developer's IDE).
|
|
241
253
|
if (!text)
|
|
242
|
-
|
|
254
|
+
respond(false);
|
|
243
255
|
if (!shieldId) {
|
|
244
|
-
|
|
245
|
-
permission: 'allow',
|
|
246
|
-
agent_message: 'FullCourtDefense hook installed but no Shield ID configured (run `fullcourtdefense configure`).',
|
|
247
|
-
}, false);
|
|
256
|
+
respond(false, undefined, 'FullCourtDefense hook installed but no Shield ID configured (run `fullcourtdefense configure`).');
|
|
248
257
|
}
|
|
249
258
|
try {
|
|
250
259
|
const controller = new AbortController();
|
|
@@ -269,12 +278,7 @@ async function hookCommand(args, config) {
|
|
|
269
278
|
clearTimeout(timer);
|
|
270
279
|
if (!resp.ok) {
|
|
271
280
|
// Backend rejected (quota, bad shield, etc.) — fail open unless told otherwise.
|
|
272
|
-
|
|
273
|
-
emit({
|
|
274
|
-
permission: blocked ? 'deny' : 'allow',
|
|
275
|
-
user_message: blocked ? `FullCourtDefense gate unavailable (HTTP ${resp.status}) — blocked by fail-closed policy.` : undefined,
|
|
276
|
-
agent_message: `FullCourtDefense gate returned HTTP ${resp.status}.`,
|
|
277
|
-
}, blocked);
|
|
281
|
+
respond(failClosed, failClosed ? `FullCourtDefense gate unavailable (HTTP ${resp.status}) — blocked by fail-closed policy.` : undefined, `FullCourtDefense gate returned HTTP ${resp.status}.`);
|
|
278
282
|
}
|
|
279
283
|
const data = await resp.json().catch(() => ({}));
|
|
280
284
|
const sh = (data._shield || {});
|
|
@@ -285,28 +289,16 @@ async function hookCommand(args, config) {
|
|
|
285
289
|
const reason = String(sh.reason || 'policy_violation');
|
|
286
290
|
const explanation = String(sh.reason || 'Flagged by FullCourtDefense.');
|
|
287
291
|
if (!isBlocked) {
|
|
288
|
-
|
|
292
|
+
respond(false);
|
|
289
293
|
}
|
|
290
294
|
// Blocked verdict. In shadow mode we annotate but let it through.
|
|
291
295
|
if (shadow) {
|
|
292
|
-
|
|
293
|
-
permission: 'allow',
|
|
294
|
-
agent_message: `[FullCourtDefense shadow] would block ${event} (${reason}): ${explanation}`,
|
|
295
|
-
}, false);
|
|
296
|
+
respond(false, undefined, `[FullCourtDefense shadow] would block ${event} (${reason}): ${explanation}`);
|
|
296
297
|
}
|
|
297
|
-
|
|
298
|
-
permission: 'deny',
|
|
299
|
-
user_message: `Blocked by FullCourtDefense — ${reason}. ${explanation}`,
|
|
300
|
-
agent_message: `FullCourtDefense blocked this ${event} as "${reason}". Do not retry; revise to remove the flagged content.`,
|
|
301
|
-
}, true);
|
|
298
|
+
respond(true, `Blocked by FullCourtDefense — ${reason}.`, `FullCourtDefense blocked this ${event} as "${reason}". Do not retry; revise to remove the flagged content.`);
|
|
302
299
|
}
|
|
303
300
|
catch (err) {
|
|
304
301
|
// Network error / timeout.
|
|
305
|
-
|
|
306
|
-
emit({
|
|
307
|
-
permission: blocked ? 'deny' : 'allow',
|
|
308
|
-
user_message: blocked ? 'FullCourtDefense gate unreachable — blocked by fail-closed policy.' : undefined,
|
|
309
|
-
agent_message: `FullCourtDefense hook error: ${err instanceof Error ? err.message : String(err)}.`,
|
|
310
|
-
}, blocked);
|
|
302
|
+
respond(failClosed, failClosed ? 'FullCourtDefense gate unreachable — blocked by fail-closed policy.' : undefined, `FullCourtDefense hook error: ${err instanceof Error ? err.message : String(err)}.`);
|
|
311
303
|
}
|
|
312
304
|
}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ const configure_1 = require("./commands/configure");
|
|
|
10
10
|
const discover_1 = require("./commands/discover");
|
|
11
11
|
const hook_1 = require("./commands/hook");
|
|
12
12
|
const installCursorHook_1 = require("./commands/installCursorHook");
|
|
13
|
-
const VERSION = '1.1.
|
|
13
|
+
const VERSION = '1.1.2';
|
|
14
14
|
function parseArgs(argv) {
|
|
15
15
|
const flags = {};
|
|
16
16
|
let command = '';
|