fullcourtdefense-cli 1.6.4 → 1.6.6
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 +39 -1
- package/dist/commands/mcpGateway.js +7 -2
- package/dist/version.json +1 -1
- package/package.json +42 -42
package/dist/commands/hook.js
CHANGED
|
@@ -222,6 +222,40 @@ function developerId() {
|
|
|
222
222
|
return 'unknown-developer';
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Normalize an identity component — MUST stay byte-for-byte identical to the MCP
|
|
227
|
+
* gateway's `safeIdentityPart` (mcpGateway.ts) so the hook and the gateway build
|
|
228
|
+
* the SAME per-server agent identity for the same server.
|
|
229
|
+
*/
|
|
230
|
+
function safeIdentityPart(value) {
|
|
231
|
+
return value
|
|
232
|
+
.trim()
|
|
233
|
+
.replace(/@.*$/, '')
|
|
234
|
+
.replace(/[^a-zA-Z0-9._-]+/g, '-')
|
|
235
|
+
.replace(/^-+|-+$/g, '')
|
|
236
|
+
.toLowerCase() || 'local-user';
|
|
237
|
+
}
|
|
238
|
+
/** Extract the MCP server name Cursor reports for a beforeMCPExecution payload. */
|
|
239
|
+
function mcpServerName(p) {
|
|
240
|
+
return str(p.mcp_server_name) || str(p.server_name) || str(p.serverName) || str(p.mcpServer) || undefined;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Runtime agent identity for a tool call. For MCP calls we use a RUNTIME-AGNOSTIC
|
|
244
|
+
* per-server identity (`<developer>-<server>`) — the client (cursor/codex/claude/...) is
|
|
245
|
+
* intentionally NOT part of the identity, because the same logical agent (the MCP server)
|
|
246
|
+
* is the same agent no matter which IDE/client invokes it. This mirrors the gateway's
|
|
247
|
+
* `perServerAgentName`, so ONE per-agent policy matches the same server across every runtime.
|
|
248
|
+
* The client is still reported separately as `agentClient` metadata for optional per-runtime
|
|
249
|
+
* constraints. Non-MCP events keep the collapsed per-developer IDE-runtime identity.
|
|
250
|
+
*/
|
|
251
|
+
function agentNameForCall(event, p) {
|
|
252
|
+
if (event === 'mcp') {
|
|
253
|
+
const server = mcpServerName(p);
|
|
254
|
+
if (server)
|
|
255
|
+
return `${safeIdentityPart(developerId())}-${safeIdentityPart(server)}`;
|
|
256
|
+
}
|
|
257
|
+
return `cursor-${developerId()}`;
|
|
258
|
+
}
|
|
225
259
|
/** Cursor conversation/session id when present, else a stable per-machine id. */
|
|
226
260
|
function sessionId(p) {
|
|
227
261
|
const fromPayload = p.conversation_id || p.conversationId || p.session_id || p.sessionId;
|
|
@@ -351,12 +385,16 @@ async function enforceActionPolicy(ctx) {
|
|
|
351
385
|
headers,
|
|
352
386
|
body: JSON.stringify({
|
|
353
387
|
shieldId,
|
|
354
|
-
|
|
388
|
+
// For MCP calls this mirrors the gateway's runtime-agnostic per-server identity
|
|
389
|
+
// (`<developer>-<server>`), so ONE per-agent policy matches the same server on the
|
|
390
|
+
// gateway path AND this in-IDE hook path, across every client/runtime.
|
|
391
|
+
agentName: agentNameForCall(event, payload),
|
|
355
392
|
toolName: call.toolName,
|
|
356
393
|
toolArgs: call.toolArgs,
|
|
357
394
|
argsSummary: summarizeToolCall(call.toolName, call.toolArgs),
|
|
358
395
|
sessionId: sessionId(payload),
|
|
359
396
|
source: 'cursor_hook',
|
|
397
|
+
...(event === 'mcp' && mcpServerName(payload) ? { mcpServer: mcpServerName(payload) } : {}),
|
|
360
398
|
...machineMetadata(),
|
|
361
399
|
}),
|
|
362
400
|
signal: controller.signal,
|
|
@@ -1022,8 +1022,13 @@ function backupFile(file) {
|
|
|
1022
1022
|
}
|
|
1023
1023
|
catch { /* best effort */ }
|
|
1024
1024
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1025
|
+
// RUNTIME-AGNOSTIC per-server agent identity: `<developer>-<server>`. The client
|
|
1026
|
+
// (cursor/codex/claude/...) is deliberately excluded — the same MCP server is the same
|
|
1027
|
+
// logical agent regardless of which IDE/runtime invokes it, so ONE per-agent policy applies
|
|
1028
|
+
// everywhere. The client is still carried separately as `agentClient` metadata (see GatewayConfig)
|
|
1029
|
+
// for optional per-runtime constraints. `agentClient` is kept as a param for signature stability.
|
|
1030
|
+
function perServerAgentName(developerName, _agentClient, serverName) {
|
|
1031
|
+
return `${safeIdentityPart(developerName)}-${safeIdentityPart(serverName)}`;
|
|
1027
1032
|
}
|
|
1028
1033
|
function wrapJsonConfigFile(file, gatewayConfig, agentClient, dryRun) {
|
|
1029
1034
|
const stats = newWrapStats();
|
package/dist/version.json
CHANGED
package/package.json
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "fullcourtdefense-cli",
|
|
3
|
-
"version": "1.6.
|
|
4
|
-
"description": "Full Court Defense CLI — security scanning for AI agents from your terminal",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"fullcourtdefense": "dist/index.js",
|
|
8
|
-
"fcd": "dist/index.js",
|
|
9
|
-
"botguard": "dist/index.js"
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"dist",
|
|
13
|
-
"README.md"
|
|
14
|
-
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "tsc && node scripts/copy-attack-corpus.js",
|
|
17
|
-
"prepublishOnly": "npm run build"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"llm",
|
|
21
|
-
"security",
|
|
22
|
-
"guardrails",
|
|
23
|
-
"ai-safety",
|
|
24
|
-
"prompt-injection",
|
|
25
|
-
"cli",
|
|
26
|
-
"red-teaming",
|
|
27
|
-
"owasp",
|
|
28
|
-
"mcp",
|
|
29
|
-
"rag"
|
|
30
|
-
],
|
|
31
|
-
"license": "MIT",
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@types/node": "^25.3.0",
|
|
34
|
-
"typescript": "^5.3.0"
|
|
35
|
-
},
|
|
36
|
-
"engines": {
|
|
37
|
-
"node": ">=18.0.0"
|
|
38
|
-
},
|
|
39
|
-
"dependencies": {
|
|
40
|
-
"yaml": "^2.8.4"
|
|
41
|
-
}
|
|
42
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "fullcourtdefense-cli",
|
|
3
|
+
"version": "1.6.6",
|
|
4
|
+
"description": "Full Court Defense CLI — security scanning for AI agents from your terminal",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"fullcourtdefense": "dist/index.js",
|
|
8
|
+
"fcd": "dist/index.js",
|
|
9
|
+
"botguard": "dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc && node scripts/copy-attack-corpus.js",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"llm",
|
|
21
|
+
"security",
|
|
22
|
+
"guardrails",
|
|
23
|
+
"ai-safety",
|
|
24
|
+
"prompt-injection",
|
|
25
|
+
"cli",
|
|
26
|
+
"red-teaming",
|
|
27
|
+
"owasp",
|
|
28
|
+
"mcp",
|
|
29
|
+
"rag"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^25.3.0",
|
|
34
|
+
"typescript": "^5.3.0"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"yaml": "^2.8.4"
|
|
41
|
+
}
|
|
42
|
+
}
|