@securecode-ai/mcp 0.5.5 → 0.5.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.
Files changed (185) hide show
  1. package/dist/api/types.d.ts +7 -0
  2. package/dist/approval/auditLog.d.ts +1 -1
  3. package/dist/approval/auditLog.js +11 -3
  4. package/dist/approval/auditLog.js.map +1 -1
  5. package/dist/approval/broker.d.ts +7 -2
  6. package/dist/approval/broker.js +239 -110
  7. package/dist/approval/broker.js.map +1 -1
  8. package/dist/approval/policy.d.ts +10 -0
  9. package/dist/approval/policy.js +104 -0
  10. package/dist/approval/policy.js.map +1 -0
  11. package/dist/approval/types.d.ts +11 -2
  12. package/dist/approval/types.js +10 -1
  13. package/dist/approval/types.js.map +1 -1
  14. package/dist/attack/agentScanExecutor.d.ts +35 -1
  15. package/dist/attack/agentScanExecutor.js +405 -76
  16. package/dist/attack/agentScanExecutor.js.map +1 -1
  17. package/dist/attack/agentScanLoop.d.ts +20 -0
  18. package/dist/attack/agentScanLoop.js +1264 -60
  19. package/dist/attack/agentScanLoop.js.map +1 -1
  20. package/dist/attack/agentScanProtocol.d.ts +382 -6
  21. package/dist/attack/agentScanProtocol.js +110 -4
  22. package/dist/attack/agentScanProtocol.js.map +1 -1
  23. package/dist/attack/agentTrace.d.ts +73 -0
  24. package/dist/attack/agentTrace.js +228 -0
  25. package/dist/attack/agentTrace.js.map +1 -0
  26. package/dist/attack/architectureScoutExecutor.d.ts +18 -0
  27. package/dist/attack/architectureScoutExecutor.js +211 -0
  28. package/dist/attack/architectureScoutExecutor.js.map +1 -0
  29. package/dist/attack/architectureScoutLoop.d.ts +36 -0
  30. package/dist/attack/architectureScoutLoop.js +403 -0
  31. package/dist/attack/architectureScoutLoop.js.map +1 -0
  32. package/dist/attack/architectureScoutProtocol.d.ts +209 -0
  33. package/dist/attack/architectureScoutProtocol.js +47 -0
  34. package/dist/attack/architectureScoutProtocol.js.map +1 -0
  35. package/dist/attack/candidateStore.d.ts +95 -0
  36. package/dist/attack/candidateStore.js +231 -0
  37. package/dist/attack/candidateStore.js.map +1 -0
  38. package/dist/attack/evidenceLedger.d.ts +67 -0
  39. package/dist/attack/evidenceLedger.js +192 -0
  40. package/dist/attack/evidenceLedger.js.map +1 -0
  41. package/dist/attack/finishGate.d.ts +62 -0
  42. package/dist/attack/finishGate.js +209 -0
  43. package/dist/attack/finishGate.js.map +1 -0
  44. package/dist/attack/fixCodeMerge.d.ts +27 -0
  45. package/dist/attack/fixCodeMerge.js +42 -0
  46. package/dist/attack/fixCodeMerge.js.map +1 -0
  47. package/dist/attack/fixVerifyLoop.d.ts +55 -0
  48. package/dist/attack/fixVerifyLoop.js +187 -0
  49. package/dist/attack/fixVerifyLoop.js.map +1 -0
  50. package/dist/attack/investigationProfiles.d.ts +36 -0
  51. package/dist/attack/investigationProfiles.js +144 -0
  52. package/dist/attack/investigationProfiles.js.map +1 -0
  53. package/dist/attack/investigationState.d.ts +227 -0
  54. package/dist/attack/investigationState.js +666 -0
  55. package/dist/attack/investigationState.js.map +1 -0
  56. package/dist/attack/mutationOperators.d.ts +22 -0
  57. package/dist/attack/mutationOperators.js +170 -0
  58. package/dist/attack/mutationOperators.js.map +1 -0
  59. package/dist/attack/mutationTest.d.ts +33 -0
  60. package/dist/attack/mutationTest.js +110 -0
  61. package/dist/attack/mutationTest.js.map +1 -0
  62. package/dist/attack/proofGate.d.ts +20 -0
  63. package/dist/attack/proofGate.js +104 -0
  64. package/dist/attack/proofGate.js.map +1 -0
  65. package/dist/attack/proofTypes.d.ts +57 -0
  66. package/dist/attack/proofTypes.js +32 -0
  67. package/dist/attack/proofTypes.js.map +1 -0
  68. package/dist/attack/protocolValidator.d.ts +50 -0
  69. package/dist/attack/protocolValidator.js +427 -0
  70. package/dist/attack/protocolValidator.js.map +1 -0
  71. package/dist/attack/qualityMetrics.d.ts +133 -0
  72. package/dist/attack/qualityMetrics.js +226 -0
  73. package/dist/attack/qualityMetrics.js.map +1 -0
  74. package/dist/attack/scanScheduler.d.ts +52 -0
  75. package/dist/attack/scanScheduler.js +265 -0
  76. package/dist/attack/scanScheduler.js.map +1 -0
  77. package/dist/attack/scanState.d.ts +58 -0
  78. package/dist/attack/scanState.js +102 -0
  79. package/dist/attack/scanState.js.map +1 -0
  80. package/dist/attack/searchIntent.d.ts +16 -0
  81. package/dist/attack/searchIntent.js +57 -0
  82. package/dist/attack/searchIntent.js.map +1 -0
  83. package/dist/attack/verifyLoop.d.ts +43 -0
  84. package/dist/attack/verifyLoop.js +314 -14
  85. package/dist/attack/verifyLoop.js.map +1 -1
  86. package/dist/attack/workItem.d.ts +57 -0
  87. package/dist/attack/workItem.js +225 -0
  88. package/dist/attack/workItem.js.map +1 -0
  89. package/dist/audit/findingReviewQueue.d.ts +109 -0
  90. package/dist/audit/findingReviewQueue.js +335 -0
  91. package/dist/audit/findingReviewQueue.js.map +1 -0
  92. package/dist/audit/scanAuditLog.d.ts +160 -0
  93. package/dist/audit/scanAuditLog.js +404 -0
  94. package/dist/audit/scanAuditLog.js.map +1 -0
  95. package/dist/dependency/dependencyChecker.js +35 -9
  96. package/dist/dependency/dependencyChecker.js.map +1 -1
  97. package/dist/dependency/exploitPriority.d.ts +33 -0
  98. package/dist/dependency/exploitPriority.js +78 -0
  99. package/dist/dependency/exploitPriority.js.map +1 -0
  100. package/dist/dependency/finding.d.ts +16 -0
  101. package/dist/dependency/osvClient.js +2 -0
  102. package/dist/dependency/osvClient.js.map +1 -1
  103. package/dist/dependency/types.d.ts +12 -1
  104. package/dist/mcp/server.js +13 -2
  105. package/dist/mcp/server.js.map +1 -1
  106. package/dist/mcp/tools.d.ts +1 -0
  107. package/dist/mcp/tools.js +127 -6
  108. package/dist/mcp/tools.js.map +1 -1
  109. package/dist/project-map/agentMemory.d.ts +83 -1
  110. package/dist/project-map/agentMemory.js +197 -7
  111. package/dist/project-map/agentMemory.js.map +1 -1
  112. package/dist/project-map/architectureContext.d.ts +202 -0
  113. package/dist/project-map/architectureContext.js +421 -0
  114. package/dist/project-map/architectureContext.js.map +1 -0
  115. package/dist/project-map/blastRadius.d.ts +54 -0
  116. package/dist/project-map/blastRadius.js +196 -0
  117. package/dist/project-map/blastRadius.js.map +1 -0
  118. package/dist/project-map/callGraphExtractor.d.ts +13 -0
  119. package/dist/project-map/callGraphExtractor.js +222 -0
  120. package/dist/project-map/callGraphExtractor.js.map +1 -0
  121. package/dist/project-map/capabilityRegistry.d.ts +46 -0
  122. package/dist/project-map/capabilityRegistry.js +91 -0
  123. package/dist/project-map/capabilityRegistry.js.map +1 -0
  124. package/dist/project-map/findTests.d.ts +29 -0
  125. package/dist/project-map/findTests.js +236 -0
  126. package/dist/project-map/findTests.js.map +1 -0
  127. package/dist/project-map/handlerInventory.d.ts +112 -0
  128. package/dist/project-map/handlerInventory.js +184 -0
  129. package/dist/project-map/handlerInventory.js.map +1 -0
  130. package/dist/project-map/implementationResolver.d.ts +43 -0
  131. package/dist/project-map/implementationResolver.js +217 -0
  132. package/dist/project-map/implementationResolver.js.map +1 -0
  133. package/dist/project-map/mapContext.d.ts +6 -1
  134. package/dist/project-map/mapContext.js +1 -0
  135. package/dist/project-map/mapContext.js.map +1 -1
  136. package/dist/project-map/scanCache.d.ts +57 -3
  137. package/dist/project-map/scanCache.js +61 -2
  138. package/dist/project-map/scanCache.js.map +1 -1
  139. package/dist/project-map/symbolIndex.d.ts +39 -0
  140. package/dist/project-map/symbolIndex.js +385 -0
  141. package/dist/project-map/symbolIndex.js.map +1 -0
  142. package/dist/tooling/agentEvalScoring.d.ts +77 -0
  143. package/dist/tooling/agentEvalScoring.js +140 -0
  144. package/dist/tooling/agentEvalScoring.js.map +1 -0
  145. package/dist/tooling/agentRegression.d.ts +53 -0
  146. package/dist/tooling/agentRegression.js +99 -0
  147. package/dist/tooling/agentRegression.js.map +1 -0
  148. package/dist/tools/agentScan.d.ts +69 -0
  149. package/dist/tools/agentScan.js +702 -43
  150. package/dist/tools/agentScan.js.map +1 -1
  151. package/dist/tools/findingReviewTools.d.ts +22 -0
  152. package/dist/tools/findingReviewTools.js +121 -0
  153. package/dist/tools/findingReviewTools.js.map +1 -0
  154. package/dist/tools/fix.js +1 -1
  155. package/dist/tools/fix.js.map +1 -1
  156. package/dist/tools/map.js +191 -1
  157. package/dist/tools/map.js.map +1 -1
  158. package/dist/tools/runTests.d.ts +2 -0
  159. package/dist/tools/runTests.js +29 -0
  160. package/dist/tools/runTests.js.map +1 -0
  161. package/dist/utils/effectMock.d.ts +1 -0
  162. package/dist/utils/effectMock.js +162 -0
  163. package/dist/utils/effectMock.js.map +1 -0
  164. package/dist/utils/gitContext.d.ts +26 -0
  165. package/dist/utils/gitContext.js +317 -0
  166. package/dist/utils/gitContext.js.map +1 -0
  167. package/dist/utils/localTestRunner.d.ts +57 -2
  168. package/dist/utils/localTestRunner.js +122 -115
  169. package/dist/utils/localTestRunner.js.map +1 -1
  170. package/dist/utils/securityConfig.d.ts +17 -0
  171. package/dist/utils/securityConfig.js +192 -0
  172. package/dist/utils/securityConfig.js.map +1 -0
  173. package/dist/utils/testCommandPolicy.d.ts +36 -0
  174. package/dist/utils/testCommandPolicy.js +252 -0
  175. package/dist/utils/testCommandPolicy.js.map +1 -0
  176. package/dist/utils/testRunner.d.ts +56 -0
  177. package/dist/utils/testRunner.js +246 -0
  178. package/dist/utils/testRunner.js.map +1 -0
  179. package/dist/utils/testSafety.d.ts +40 -2
  180. package/dist/utils/testSafety.js +205 -26
  181. package/dist/utils/testSafety.js.map +1 -1
  182. package/dist/utils/verificationSandbox.d.ts +113 -0
  183. package/dist/utils/verificationSandbox.js +656 -0
  184. package/dist/utils/verificationSandbox.js.map +1 -0
  185. package/package.json +1 -1
@@ -0,0 +1,50 @@
1
+ /**
2
+ * MCP-side runtime validation of API responses.
3
+ *
4
+ * The API is a trusted service we control, but the wire is untrusted: a
5
+ * misconfigured proxy, a response from a stale API version, or a
6
+ * man-in-the-middle on an unencrypted hop could deliver a malformed
7
+ * response that the MCP would otherwise execute as ground truth. The
8
+ * previous code fed `stepResp.next` directly into `executeAction`'s
9
+ * switch — an unknown action type fell through to a no-op, and a
10
+ * malformed action would either crash or silently produce bad state.
11
+ *
12
+ * This module validates the shape of:
13
+ * - AgentScanStartResponse
14
+ * - AgentScanStepResponse (and the embedded AgentScanAction)
15
+ * - AgentScanToolResponse
16
+ * - VerifyGenerateResponse (POST /verify/generate)
17
+ * - VerifyAnalyzeResponse (POST /verify/analyze)
18
+ *
19
+ * On validation failure, the caller treats it as a controlled `spawn_failed`
20
+ * or `degraded` result rather than executing the malformed action.
21
+ *
22
+ * Validation is strict-by-default: unknown fields are ignored (forward-
23
+ * compatible), but required fields and type constraints are enforced.
24
+ * Findings are NOT validated here — the agent loop owns finding validation
25
+ * (validateFinish); we only validate the wire envelope and the action
26
+ * discriminator.
27
+ */
28
+ import type { AgentScanAction, AgentScanStartResponse, AgentScanStepResponse, AgentScanToolResponse } from '../attack/agentScanProtocol';
29
+ import type { VerifyGenerateResponse, VerifyAnalyzeResponse } from '../api/types';
30
+ export interface ValidationOk<T> {
31
+ ok: true;
32
+ value: T;
33
+ }
34
+ export interface ValidationErr {
35
+ ok: false;
36
+ error: string;
37
+ }
38
+ export type ValidationResult<T> = ValidationOk<T> | ValidationErr;
39
+ /**
40
+ * Validate an AgentScanAction. Returns the action typed, or an error.
41
+ * Does NOT validate finish.findings deeply — the API's parseAction +
42
+ * validateFinish already did that. We only check the discriminator and
43
+ * the primary fields the MCP executor needs.
44
+ */
45
+ export declare function validateAction(raw: unknown): ValidationResult<AgentScanAction>;
46
+ export declare function validateStartResponse(raw: unknown): ValidationResult<AgentScanStartResponse>;
47
+ export declare function validateStepResponse(raw: unknown): ValidationResult<AgentScanStepResponse>;
48
+ export declare function validateToolResponse(raw: unknown): ValidationResult<AgentScanToolResponse>;
49
+ export declare function validateVerifyGenerateResponse(raw: unknown): ValidationResult<VerifyGenerateResponse>;
50
+ export declare function validateVerifyAnalyzeResponse(raw: unknown): ValidationResult<VerifyAnalyzeResponse>;
@@ -0,0 +1,427 @@
1
+ "use strict";
2
+ /**
3
+ * MCP-side runtime validation of API responses.
4
+ *
5
+ * The API is a trusted service we control, but the wire is untrusted: a
6
+ * misconfigured proxy, a response from a stale API version, or a
7
+ * man-in-the-middle on an unencrypted hop could deliver a malformed
8
+ * response that the MCP would otherwise execute as ground truth. The
9
+ * previous code fed `stepResp.next` directly into `executeAction`'s
10
+ * switch — an unknown action type fell through to a no-op, and a
11
+ * malformed action would either crash or silently produce bad state.
12
+ *
13
+ * This module validates the shape of:
14
+ * - AgentScanStartResponse
15
+ * - AgentScanStepResponse (and the embedded AgentScanAction)
16
+ * - AgentScanToolResponse
17
+ * - VerifyGenerateResponse (POST /verify/generate)
18
+ * - VerifyAnalyzeResponse (POST /verify/analyze)
19
+ *
20
+ * On validation failure, the caller treats it as a controlled `spawn_failed`
21
+ * or `degraded` result rather than executing the malformed action.
22
+ *
23
+ * Validation is strict-by-default: unknown fields are ignored (forward-
24
+ * compatible), but required fields and type constraints are enforced.
25
+ * Findings are NOT validated here — the agent loop owns finding validation
26
+ * (validateFinish); we only validate the wire envelope and the action
27
+ * discriminator.
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.validateAction = validateAction;
31
+ exports.validateStartResponse = validateStartResponse;
32
+ exports.validateStepResponse = validateStepResponse;
33
+ exports.validateToolResponse = validateToolResponse;
34
+ exports.validateVerifyGenerateResponse = validateVerifyGenerateResponse;
35
+ exports.validateVerifyAnalyzeResponse = validateVerifyAnalyzeResponse;
36
+ function ok(value) { return { ok: true, value }; }
37
+ function err(error) { return { ok: false, error }; }
38
+ function isObject(x) {
39
+ return typeof x === 'object' && x !== null && !Array.isArray(x);
40
+ }
41
+ function isString(x) { return typeof x === 'string'; }
42
+ function isNumber(x) { return typeof x === 'number' && Number.isFinite(x); }
43
+ function isBool(x) { return typeof x === 'boolean'; }
44
+ function isOptionalString(x) { return x === undefined || x === null || isString(x); }
45
+ function isOptionalNumber(x) { return x === undefined || x === null || isNumber(x); }
46
+ // ── Action validation ───────────────────────────────────────────────────────
47
+ const VALID_ACTION_TYPES = new Set([
48
+ 'read_file', 'search_code', 'trace_flow', 'trace_flow_cross_file',
49
+ 'check_guard', 'check_policy', 'get_endpoints', 'list_imports',
50
+ 'list_files', 'call_graph', 'git_blame', 'git_history', 'git_diff',
51
+ 'check_dependencies', 'read_config', 'find_definition',
52
+ 'find_references', 'find_tests', 'run_tests',
53
+ 'finish', 'system_event',
54
+ ]);
55
+ const VALID_ATTACK_TYPES = new Set([
56
+ 'sql_injection', 'nosql_injection', 'command_injection', 'xss', 'ssrf',
57
+ 'path_traversal', 'open_redirect', 'prototype_pollution',
58
+ 'insecure_deserialization', 'broken_access_control',
59
+ ]);
60
+ const VALID_SYSTEM_EVENT_TYPES = new Set(['critique', 'error', 'blocked', 'budget', 'finish_gate']);
61
+ const VALID_SEVERITIES = new Set(['critical', 'high', 'medium', 'low']);
62
+ /**
63
+ * Validate an AgentScanAction. Returns the action typed, or an error.
64
+ * Does NOT validate finish.findings deeply — the API's parseAction +
65
+ * validateFinish already did that. We only check the discriminator and
66
+ * the primary fields the MCP executor needs.
67
+ */
68
+ function validateAction(raw) {
69
+ if (!isObject(raw))
70
+ return err('action is not an object');
71
+ const type = raw.type;
72
+ if (!isString(type) || !VALID_ACTION_TYPES.has(type)) {
73
+ return err(`action.type is missing or unknown: ${String(type)}`);
74
+ }
75
+ switch (type) {
76
+ case 'read_file': {
77
+ if (!isString(raw.path) || raw.path.length === 0) {
78
+ return err('read_file requires non-empty string "path"');
79
+ }
80
+ if (!isOptionalNumber(raw.startLine) || !isOptionalNumber(raw.endLine)) {
81
+ return err('read_file startLine/endLine must be numbers or null');
82
+ }
83
+ return ok(raw);
84
+ }
85
+ case 'search_code': {
86
+ if (!isString(raw.pattern) || raw.pattern.length === 0) {
87
+ return err('search_code requires non-empty string "pattern"');
88
+ }
89
+ if (!isOptionalString(raw.glob))
90
+ return err('search_code glob must be string or null');
91
+ return ok(raw);
92
+ }
93
+ case 'trace_flow': {
94
+ if (!isString(raw.filePath) || raw.filePath.length === 0) {
95
+ return err('trace_flow requires non-empty string "filePath"');
96
+ }
97
+ return ok(raw);
98
+ }
99
+ case 'trace_flow_cross_file': {
100
+ if (!isString(raw.filePath) || raw.filePath.length === 0) {
101
+ return err('trace_flow_cross_file requires non-empty string "filePath"');
102
+ }
103
+ if (!isOptionalNumber(raw.maxDepth))
104
+ return err('maxDepth must be a number or null');
105
+ return ok(raw);
106
+ }
107
+ case 'check_guard': {
108
+ if (!isString(raw.filePath) || raw.filePath.length === 0)
109
+ return err('check_guard requires "filePath"');
110
+ if (!isString(raw.guardName) || raw.guardName.length === 0)
111
+ return err('check_guard requires "guardName"');
112
+ if (!isString(raw.attackType) || !VALID_ATTACK_TYPES.has(raw.attackType)) {
113
+ return err(`check_guard attackType is not a known AttackType: ${String(raw.attackType)}`);
114
+ }
115
+ return ok(raw);
116
+ }
117
+ case 'check_policy': {
118
+ if (!isString(raw.filePath) || raw.filePath.length === 0)
119
+ return err('check_policy requires "filePath"');
120
+ return ok(raw);
121
+ }
122
+ case 'get_endpoints': {
123
+ if (!isOptionalString(raw.glob))
124
+ return err('get_endpoints glob must be string or null');
125
+ return ok(raw);
126
+ }
127
+ case 'list_imports': {
128
+ if (!isString(raw.filePath) || raw.filePath.length === 0)
129
+ return err('list_imports requires "filePath"');
130
+ return ok(raw);
131
+ }
132
+ case 'list_files': {
133
+ if (!isOptionalString(raw.path))
134
+ return err('list_files path must be string or null');
135
+ if (!isOptionalString(raw.glob))
136
+ return err('list_files glob must be string or null');
137
+ return ok(raw);
138
+ }
139
+ case 'call_graph': {
140
+ if (!isString(raw.filePath) || raw.filePath.length === 0)
141
+ return err('call_graph requires "filePath"');
142
+ if (!isOptionalString(raw.functionName))
143
+ return err('call_graph functionName must be string or null');
144
+ return ok(raw);
145
+ }
146
+ case 'git_blame': {
147
+ if (!isString(raw.filePath) || raw.filePath.length === 0)
148
+ return err('git_blame requires "filePath"');
149
+ if (!isOptionalNumber(raw.startLine))
150
+ return err('git_blame startLine must be number or null');
151
+ if (!isOptionalNumber(raw.endLine))
152
+ return err('git_blame endLine must be number or null');
153
+ return ok(raw);
154
+ }
155
+ case 'git_history': {
156
+ if (!isOptionalString(raw.filePath))
157
+ return err('git_history filePath must be string or null');
158
+ if (!isOptionalString(raw.functionName))
159
+ return err('git_history functionName must be string or null');
160
+ if (!isOptionalNumber(raw.limit))
161
+ return err('git_history limit must be number or null');
162
+ return ok(raw);
163
+ }
164
+ case 'git_diff': {
165
+ if (!isString(raw.baseRef) || raw.baseRef.length === 0)
166
+ return err('git_diff requires non-empty "baseRef"');
167
+ if (!isOptionalString(raw.headRef))
168
+ return err('git_diff headRef must be string or null');
169
+ return ok(raw);
170
+ }
171
+ case 'check_dependencies':
172
+ return ok(raw);
173
+ case 'read_config': {
174
+ if (!isString(raw.configKind) || !['auth', 'cors', 'rate_limit', 'headers', 'env', 'all'].includes(raw.configKind)) {
175
+ return err('read_config requires "configKind" (auth, cors, rate_limit, headers, env, all)');
176
+ }
177
+ return ok(raw);
178
+ }
179
+ case 'find_definition': {
180
+ if (!isString(raw.filePath) || raw.filePath.length === 0)
181
+ return err('find_definition requires "filePath"');
182
+ if (!isString(raw.symbol) || raw.symbol.length === 0)
183
+ return err('find_definition requires "symbol"');
184
+ if (!isOptionalNumber(raw.line))
185
+ return err('find_definition line must be number or null');
186
+ return ok(raw);
187
+ }
188
+ case 'find_references': {
189
+ if (!isString(raw.filePath) || raw.filePath.length === 0)
190
+ return err('find_references requires "filePath"');
191
+ if (!isString(raw.symbol) || raw.symbol.length === 0)
192
+ return err('find_references requires "symbol"');
193
+ if (!isOptionalNumber(raw.line))
194
+ return err('find_references line must be number or null');
195
+ return ok(raw);
196
+ }
197
+ case 'find_tests': {
198
+ if (!isString(raw.filePath) || raw.filePath.length === 0)
199
+ return err('find_tests requires "filePath"');
200
+ if (!isOptionalString(raw.symbol))
201
+ return err('find_tests symbol must be string or null');
202
+ return ok(raw);
203
+ }
204
+ case 'run_tests': {
205
+ if (!isString(raw.mode) || (raw.mode !== 'existing' && raw.mode !== 'generated')) {
206
+ return err('run_tests requires "mode" (existing or generated)');
207
+ }
208
+ if (raw.mode === 'existing') {
209
+ if (raw.testFiles !== undefined && raw.testFiles !== null) {
210
+ if (!Array.isArray(raw.testFiles))
211
+ return err('run_tests testFiles must be an array');
212
+ }
213
+ if (!isOptionalString(raw.testPattern))
214
+ return err('run_tests testPattern must be string or null');
215
+ if (!isOptionalString(raw.packageManager))
216
+ return err('run_tests packageManager must be string or null');
217
+ }
218
+ else {
219
+ if (!isString(raw.script) || raw.script.length === 0)
220
+ return err('run_tests generated mode requires "script"');
221
+ if (!isString(raw.runner) || raw.runner.length === 0)
222
+ return err('run_tests generated mode requires "runner"');
223
+ if (!isOptionalString(raw.setupScript))
224
+ return err('run_tests setupScript must be string or null');
225
+ }
226
+ if (!isOptionalNumber(raw.timeoutMs))
227
+ return err('run_tests timeoutMs must be number or null');
228
+ return ok(raw);
229
+ }
230
+ case 'finish': {
231
+ if (!Array.isArray(raw.findings))
232
+ return err('finish requires "findings" array');
233
+ // Light per-finding check: line must be a positive int, type must be non-empty, severity must be valid.
234
+ for (let i = 0; i < raw.findings.length; i++) {
235
+ const f = raw.findings[i];
236
+ if (!isObject(f))
237
+ return err(`finding[${i}] is not an object`);
238
+ if (!isNumber(f.line) || f.line < 1)
239
+ return err(`finding[${i}].line must be a positive integer`);
240
+ if (!isString(f.type) || f.type.length === 0)
241
+ return err(`finding[${i}].type must be a non-empty string`);
242
+ if (!isString(f.severity) || !VALID_SEVERITIES.has(f.severity)) {
243
+ return err(`finding[${i}].severity must be one of critical|high|medium|low`);
244
+ }
245
+ if (!isNumber(f.confidence) || f.confidence < 0 || f.confidence > 100) {
246
+ return err(`finding[${i}].confidence must be 0-100`);
247
+ }
248
+ }
249
+ if (!isString(raw.summary))
250
+ return err('finish requires "summary" string');
251
+ return ok(raw);
252
+ }
253
+ case 'system_event': {
254
+ if (!isString(raw.eventType) || !VALID_SYSTEM_EVENT_TYPES.has(raw.eventType)) {
255
+ return err(`system_event.eventType is missing or unknown: ${String(raw.eventType)}`);
256
+ }
257
+ if (!isString(raw.message) || raw.message.length === 0) {
258
+ return err('system_event requires non-empty "message"');
259
+ }
260
+ return ok(raw);
261
+ }
262
+ default:
263
+ return err(`unhandled action type: ${type}`);
264
+ }
265
+ }
266
+ // ── Start response ──────────────────────────────────────────────────────────
267
+ function validateStartResponse(raw) {
268
+ if (!isObject(raw))
269
+ return err('start response is not an object');
270
+ if (!isString(raw.runId) || raw.runId.length === 0)
271
+ return err('start response missing runId');
272
+ if (!isObject(raw.budget))
273
+ return err('start response missing budget');
274
+ if (!isNumber(raw.budget.stepsRemaining))
275
+ return err('budget.stepsRemaining must be a number');
276
+ if (!isNumber(raw.budget.costSpentUsd))
277
+ return err('budget.costSpentUsd must be a number');
278
+ if (!isNumber(raw.budget.costCapUsd))
279
+ return err('budget.costCapUsd must be a number');
280
+ if (raw.budget.stepsGranted !== undefined && !isNumber(raw.budget.stepsGranted))
281
+ return err('budget.stepsGranted must be a number');
282
+ if (raw.budget.hardMaxSteps !== undefined && !isNumber(raw.budget.hardMaxSteps))
283
+ return err('budget.hardMaxSteps must be a number');
284
+ if (raw.budget.extensionsGranted !== undefined && !isNumber(raw.budget.extensionsGranted))
285
+ return err('budget.extensionsGranted must be a number');
286
+ if (!isString(raw.refundId) || raw.refundId.length === 0)
287
+ return err('start response missing refundId');
288
+ // scanCredits optional but if present must be a number
289
+ if (raw.scanCredits !== undefined && !isNumber(raw.scanCredits))
290
+ return err('scanCredits must be a number');
291
+ return ok(raw);
292
+ }
293
+ // ── Step response ───────────────────────────────────────────────────────────
294
+ function validateStepResponse(raw) {
295
+ if (!isObject(raw))
296
+ return err('step response is not an object');
297
+ // next may be null or an action.
298
+ if (raw.next !== null && raw.next !== undefined) {
299
+ const actionResult = validateAction(raw.next);
300
+ if (!actionResult.ok)
301
+ return err(`step response next: ${actionResult.error}`);
302
+ }
303
+ if (!isNumber(raw.costUsd))
304
+ return err('step response costUsd must be a number');
305
+ if (!isNumber(raw.tokens))
306
+ return err('step response tokens must be a number');
307
+ if (!isBool(raw.degraded))
308
+ return err('step response degraded must be a boolean');
309
+ if (!isBool(raw.costCapped))
310
+ return err('step response costCapped must be a boolean');
311
+ if (!isNumber(raw.stepsRemaining))
312
+ return err('step response stepsRemaining must be a number');
313
+ // systemEvent optional; if present must be a valid system_event action.
314
+ if (raw.systemEvent !== undefined && raw.systemEvent !== null) {
315
+ const evResult = validateAction(raw.systemEvent);
316
+ if (!evResult.ok)
317
+ return err(`step response systemEvent: ${evResult.error}`);
318
+ // Additionally, systemEvent must actually be a system_event (not some other action type).
319
+ if (!isObject(raw.systemEvent) || raw.systemEvent.type !== 'system_event') {
320
+ return err('step response systemEvent must have type "system_event"');
321
+ }
322
+ }
323
+ return ok(raw);
324
+ }
325
+ // ── Tool response ────────────────────────────────────────────────────────────
326
+ function validateToolResponse(raw) {
327
+ if (!isObject(raw))
328
+ return err('tool response is not an object');
329
+ if (!isString(raw.observation))
330
+ return err('tool response observation must be a string');
331
+ // Cap observation length so a compromised API can't blow out the transcript.
332
+ const MAX_OBS = 64 * 1024;
333
+ if (raw.observation.length > MAX_OBS) {
334
+ // Truncate rather than reject — the observation is still useful.
335
+ raw.observation = raw.observation.slice(0, MAX_OBS) + '… [truncated by MCP validator]';
336
+ }
337
+ return ok(raw);
338
+ }
339
+ // ── Verify generate response ───────────────────────────────────────────────
340
+ //
341
+ // POST /verify/generate returns a test script + runner for local execution.
342
+ // The MCP feeds testScript directly into the sandbox, so a malformed response
343
+ // can cause unsafe or broken execution. Validate before use.
344
+ const VALID_VERIFY_RUNNERS = new Set([
345
+ 'node', 'tsx', 'bun', 'deno', 'python', 'python3',
346
+ 'pnpm-tsx', 'yarn-tsx',
347
+ ]);
348
+ const MAX_TEST_SCRIPT_BYTES = 64 * 1024;
349
+ const MAX_SETUP_SCRIPT_BYTES = 32 * 1024;
350
+ function validateVerifyGenerateResponse(raw) {
351
+ if (!isObject(raw))
352
+ return err('verify generate response is not an object');
353
+ if (!isBool(raw.canTest))
354
+ return err('verify generate response canTest must be a boolean');
355
+ if (raw.canTest) {
356
+ if (!isString(raw.testScript) || raw.testScript.length === 0) {
357
+ return err('verify generate response: canTest=true requires non-empty "testScript"');
358
+ }
359
+ if (raw.testScript.length > MAX_TEST_SCRIPT_BYTES) {
360
+ return err(`verify generate response: testScript too large (${raw.testScript.length} > ${MAX_TEST_SCRIPT_BYTES})`);
361
+ }
362
+ if (!isString(raw.runner) || raw.runner.length === 0) {
363
+ return err('verify generate response: canTest=true requires "runner"');
364
+ }
365
+ if (!VALID_VERIFY_RUNNERS.has(raw.runner)) {
366
+ return err(`verify generate response: runner "${raw.runner}" is not supported (valid: ${[...VALID_VERIFY_RUNNERS].join(', ')})`);
367
+ }
368
+ }
369
+ else {
370
+ if (!isString(raw.skipReason) || raw.skipReason.length === 0) {
371
+ return err('verify generate response: canTest=false requires non-empty "skipReason"');
372
+ }
373
+ }
374
+ if (raw.setupScript !== undefined && raw.setupScript !== null) {
375
+ if (!isString(raw.setupScript))
376
+ return err('verify generate response: setupScript must be a string or null');
377
+ if (raw.setupScript.length > MAX_SETUP_SCRIPT_BYTES) {
378
+ return err(`verify generate response: setupScript too large (${raw.setupScript.length} > ${MAX_SETUP_SCRIPT_BYTES})`);
379
+ }
380
+ }
381
+ if (raw.description !== undefined && raw.description !== null) {
382
+ if (!isString(raw.description))
383
+ return err('verify generate response: description must be a string or null');
384
+ }
385
+ if (raw.scanCredits !== undefined && raw.scanCredits !== null) {
386
+ if (!isNumber(raw.scanCredits))
387
+ return err('verify generate response: scanCredits must be a number or null');
388
+ }
389
+ if (raw.costUsd !== undefined && raw.costUsd !== null) {
390
+ if (!isNumber(raw.costUsd))
391
+ return err('verify generate response: costUsd must be a number or null');
392
+ }
393
+ return ok(raw);
394
+ }
395
+ // ── Verify analyze response ────────────────────────────────────────────────
396
+ //
397
+ // POST /verify/analyze returns a verdict (PROVEN/UNPROVEN/INCONCLUSIVE),
398
+ // a reason string, and a shouldRetry flag. The verify loop uses shouldRetry
399
+ // to decide whether to generate another test. A malformed response can cause
400
+ // infinite retries or a wrong verdict.
401
+ const VALID_VERIFY_VERDICTS = new Set(['PROVEN', 'UNPROVEN', 'INCONCLUSIVE']);
402
+ function validateVerifyAnalyzeResponse(raw) {
403
+ if (!isObject(raw))
404
+ return err('verify analyze response is not an object');
405
+ if (!isString(raw.verdict) || !VALID_VERIFY_VERDICTS.has(raw.verdict)) {
406
+ return err(`verify analyze response: verdict must be one of PROVEN|UNPROVEN|INCONCLUSIVE, got "${String(raw.verdict)}"`);
407
+ }
408
+ if (!isString(raw.reason) || raw.reason.length === 0) {
409
+ return err('verify analyze response: reason must be a non-empty string');
410
+ }
411
+ if (!isBool(raw.shouldRetry))
412
+ return err('verify analyze response: shouldRetry must be a boolean');
413
+ // PROVEN and UNPROVEN are definitive — retrying makes no sense.
414
+ if ((raw.verdict === 'PROVEN' || raw.verdict === 'UNPROVEN') && raw.shouldRetry === true) {
415
+ return err(`verify analyze response: verdict "${raw.verdict}" cannot have shouldRetry=true (definitive verdict)`);
416
+ }
417
+ if (raw.scanCredits !== undefined && raw.scanCredits !== null) {
418
+ if (!isNumber(raw.scanCredits))
419
+ return err('verify analyze response: scanCredits must be a number or null');
420
+ }
421
+ if (raw.costUsd !== undefined && raw.costUsd !== null) {
422
+ if (!isNumber(raw.costUsd))
423
+ return err('verify analyze response: costUsd must be a number or null');
424
+ }
425
+ return ok(raw);
426
+ }
427
+ //# sourceMappingURL=protocolValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocolValidator.js","sourceRoot":"","sources":["../../src/attack/protocolValidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Scan quality metrics — tracks measurable quality indicators throughout
3
+ * the agent scan so the final result includes a structured quality scorecard.
4
+ *
5
+ * Metrics are tracked locally in the MCP loop and included in the scan
6
+ * result/audit. They are NOT sent to the API — they are for the MCP and
7
+ * the caller to evaluate scan quality.
8
+ */
9
+ export interface ScanQualityMetrics {
10
+ reads: {
11
+ total: number;
12
+ successful: number;
13
+ duplicate: number;
14
+ highOverlap: number;
15
+ partialNew: number;
16
+ newCoverage: number;
17
+ blocked: number;
18
+ truncated: number;
19
+ invalid: number;
20
+ };
21
+ coverage: {
22
+ totalLines: number;
23
+ coveredLines: number;
24
+ coveragePercentage: number;
25
+ uncoveredRangeCount: number;
26
+ largestUncoveredRange: {
27
+ start: number;
28
+ end: number;
29
+ } | null;
30
+ };
31
+ tools: {
32
+ totalActions: number;
33
+ analysisToolCount: number;
34
+ distinctToolsUsed: string[];
35
+ readCount: number;
36
+ searchCount: number;
37
+ traceFlowCount: number;
38
+ checkGuardCount: number;
39
+ checkPolicyCount: number;
40
+ getEndpointsCount: number;
41
+ readConfigCount: number;
42
+ findTestsCount: number;
43
+ callGraphCount: number;
44
+ };
45
+ candidates: {
46
+ total: number;
47
+ discovered: number;
48
+ investigating: number;
49
+ supported: number;
50
+ verified: number;
51
+ unproven: number;
52
+ inconclusive: number;
53
+ rejected: number;
54
+ merged: number;
55
+ blocked: number;
56
+ };
57
+ finish: {
58
+ attempts: number;
59
+ rejections: number;
60
+ forcedTermination: boolean;
61
+ terminationReason: string;
62
+ critiqueFired: number;
63
+ finishGateFired: number;
64
+ };
65
+ output: {
66
+ malformedOutputCount: number;
67
+ sanitizedFindings: number;
68
+ downgradedFindings: number;
69
+ };
70
+ proof: {
71
+ requiredEvidenceChainRate: number;
72
+ rootCauseCorrelationRate: number;
73
+ resolvedArchitectureRiskRate: number;
74
+ structuredCrossFileFlowRate: number;
75
+ highPriorityGapCount: number;
76
+ unsupportedFindingCount: number;
77
+ };
78
+ budget: {
79
+ stepsUsed: number;
80
+ stepsGranted: number;
81
+ extensionsGranted: number;
82
+ costSpentUsd: number;
83
+ costCapUsd: number;
84
+ wallClockMs: number;
85
+ elapsedMs: number;
86
+ };
87
+ }
88
+ export declare function createQualityMetrics(): ScanQualityMetrics;
89
+ export declare class QualityMetricsTracker {
90
+ private metrics;
91
+ constructor();
92
+ recordRead(classification: string, truncated: boolean): void;
93
+ recordToolUse(toolType: string): void;
94
+ recordCoverage(totalLines: number, coveredLines: number, uncoveredRangeCount: number, largestUncovered: {
95
+ start: number;
96
+ end: number;
97
+ } | null): void;
98
+ recordCandidateSnapshot(snapshot: {
99
+ total: number;
100
+ discovered: number;
101
+ investigating: number;
102
+ supported: number;
103
+ verified: number;
104
+ unproven: number;
105
+ inconclusive: number;
106
+ rejected: number;
107
+ merged: number;
108
+ blocked: number;
109
+ }): void;
110
+ recordFinishAttempt(): void;
111
+ recordFinishRejection(): void;
112
+ recordCritique(): void;
113
+ recordFinishGate(): void;
114
+ recordForcedTermination(reason: string): void;
115
+ recordTermination(reason: string): void;
116
+ recordMalformedOutput(): void;
117
+ recordSanitizedFinding(): void;
118
+ recordDowngradedFinding(): void;
119
+ recordBudget(stepsUsed: number, stepsGranted: number, extensionsGranted: number, costSpentUsd: number, costCapUsd: number, wallClockMs: number, elapsedMs: number): void;
120
+ recordProofMetrics(input: {
121
+ totalFindings: number;
122
+ supportedFindings: number;
123
+ totalRisks: number;
124
+ resolvedRisks: number;
125
+ structuredFlows: number;
126
+ totalFlows: number;
127
+ highPriorityGaps: number;
128
+ unsupportedFindings: number;
129
+ rootCauseGroups: number;
130
+ totalCandidates: number;
131
+ }): void;
132
+ getMetrics(): ScanQualityMetrics;
133
+ }