@bryan-thompson/inspector-assessment-client 1.26.5 → 1.26.7

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 (78) hide show
  1. package/dist/assets/{OAuthCallback-DpdInvWI.js → OAuthCallback-CCWVtjr7.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-D1ImpKK5.js → OAuthDebugCallback-DqbXfUi4.js} +1 -1
  3. package/dist/assets/{index-umcoGmYw.js → index-CsDJSSWq.js} +4 -4
  4. package/dist/index.html +1 -1
  5. package/lib/lib/assessment/configTypes.d.ts +2 -0
  6. package/lib/lib/assessment/configTypes.d.ts.map +1 -1
  7. package/lib/lib/securityPatterns.d.ts +4 -2
  8. package/lib/lib/securityPatterns.d.ts.map +1 -1
  9. package/lib/lib/securityPatterns.js +146 -2
  10. package/lib/services/assessment/modules/AUPComplianceAssessor.js +9 -9
  11. package/lib/services/assessment/modules/AuthenticationAssessor.js +4 -4
  12. package/lib/services/assessment/modules/BaseAssessor.d.ts +0 -14
  13. package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -1
  14. package/lib/services/assessment/modules/BaseAssessor.js +1 -33
  15. package/lib/services/assessment/modules/CrossCapabilitySecurityAssessor.js +1 -1
  16. package/lib/services/assessment/modules/DeveloperExperienceAssessor.js +1 -1
  17. package/lib/services/assessment/modules/DocumentationAssessor.js +2 -2
  18. package/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts.map +1 -1
  19. package/lib/services/assessment/modules/ErrorHandlingAssessor.js +8 -8
  20. package/lib/services/assessment/modules/ExternalAPIScannerAssessor.d.ts.map +1 -1
  21. package/lib/services/assessment/modules/ExternalAPIScannerAssessor.js +3 -3
  22. package/lib/services/assessment/modules/FunctionalityAssessor.js +9 -9
  23. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -1
  24. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +12 -12
  25. package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
  26. package/lib/services/assessment/modules/ManifestValidationAssessor.js +9 -5
  27. package/lib/services/assessment/modules/PortabilityAssessor.d.ts.map +1 -1
  28. package/lib/services/assessment/modules/PortabilityAssessor.js +3 -3
  29. package/lib/services/assessment/modules/ProhibitedLibrariesAssessor.js +4 -4
  30. package/lib/services/assessment/modules/PromptAssessor.js +2 -2
  31. package/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
  32. package/lib/services/assessment/modules/ProtocolComplianceAssessor.js +7 -7
  33. package/lib/services/assessment/modules/ProtocolConformanceAssessor.js +1 -1
  34. package/lib/services/assessment/modules/ResourceAssessor.js +1 -1
  35. package/lib/services/assessment/modules/SecurityAssessor.d.ts +25 -2
  36. package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
  37. package/lib/services/assessment/modules/SecurityAssessor.js +149 -17
  38. package/lib/services/assessment/modules/TemporalAssessor.d.ts.map +1 -1
  39. package/lib/services/assessment/modules/TemporalAssessor.js +10 -10
  40. package/lib/services/assessment/modules/ToolAnnotationAssessor.js +9 -9
  41. package/lib/services/assessment/modules/UsabilityAssessor.js +1 -1
  42. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -1
  43. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +37 -0
  44. package/lib/services/assessment/modules/index.d.ts +3 -0
  45. package/lib/services/assessment/modules/index.d.ts.map +1 -1
  46. package/lib/services/assessment/modules/securityTests/ChainExecutionTester.d.ts +104 -0
  47. package/lib/services/assessment/modules/securityTests/ChainExecutionTester.d.ts.map +1 -0
  48. package/lib/services/assessment/modules/securityTests/ChainExecutionTester.js +257 -0
  49. package/lib/services/assessment/modules/securityTests/ConfidenceScorer.d.ts +57 -0
  50. package/lib/services/assessment/modules/securityTests/ConfidenceScorer.d.ts.map +1 -0
  51. package/lib/services/assessment/modules/securityTests/ConfidenceScorer.js +199 -0
  52. package/lib/services/assessment/modules/securityTests/CrossToolStateTester.d.ts +91 -0
  53. package/lib/services/assessment/modules/securityTests/CrossToolStateTester.d.ts.map +1 -0
  54. package/lib/services/assessment/modules/securityTests/CrossToolStateTester.js +225 -0
  55. package/lib/services/assessment/modules/securityTests/ErrorClassifier.d.ts +57 -0
  56. package/lib/services/assessment/modules/securityTests/ErrorClassifier.d.ts.map +1 -0
  57. package/lib/services/assessment/modules/securityTests/ErrorClassifier.js +113 -0
  58. package/lib/services/assessment/modules/securityTests/ExecutionArtifactDetector.d.ts +49 -0
  59. package/lib/services/assessment/modules/securityTests/ExecutionArtifactDetector.d.ts.map +1 -0
  60. package/lib/services/assessment/modules/securityTests/ExecutionArtifactDetector.js +74 -0
  61. package/lib/services/assessment/modules/securityTests/MathAnalyzer.d.ts +58 -0
  62. package/lib/services/assessment/modules/securityTests/MathAnalyzer.d.ts.map +1 -0
  63. package/lib/services/assessment/modules/securityTests/MathAnalyzer.js +251 -0
  64. package/lib/services/assessment/modules/securityTests/SafeResponseDetector.d.ts +59 -0
  65. package/lib/services/assessment/modules/securityTests/SafeResponseDetector.d.ts.map +1 -0
  66. package/lib/services/assessment/modules/securityTests/SafeResponseDetector.js +151 -0
  67. package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts +349 -0
  68. package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts.map +1 -0
  69. package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.js +904 -0
  70. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -1
  71. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +49 -24
  72. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +122 -85
  73. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -1
  74. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +443 -1176
  75. package/lib/services/assessment/modules/securityTests/index.d.ts +3 -1
  76. package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -1
  77. package/lib/services/assessment/modules/securityTests/index.js +2 -0
  78. package/package.json +1 -1
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Cross-Tool State Tester
3
+ * Tests for privilege escalation by calling tools in sequence
4
+ *
5
+ * Issue #92, Challenge #7: Cross-tool state-based authorization bypass
6
+ * Detects when one tool can modify shared state that affects another tool's authorization.
7
+ *
8
+ * Attack flow:
9
+ * 1. Call admin_action → should get "access denied"
10
+ * 2. Call config_modifier with "admin_mode=true"
11
+ * 3. Call admin_action again → if now succeeds, VULNERABLE
12
+ */
13
+ /**
14
+ * Tests for cross-tool privilege escalation via shared mutable state
15
+ */
16
+ export class CrossToolStateTester {
17
+ verbose;
18
+ constructor(config = {}) {
19
+ // Note: config.timeout is accepted but tool call timeout is handled externally
20
+ this.verbose = config.verbose ?? false;
21
+ }
22
+ /**
23
+ * Log message if verbose logging is enabled
24
+ */
25
+ log(message) {
26
+ if (this.verbose) {
27
+ // eslint-disable-next-line no-console
28
+ console.log(`[CrossToolStateTester] ${message}`);
29
+ }
30
+ }
31
+ /**
32
+ * Identify potential cross-tool pairs for testing
33
+ * Looks for admin_action/privileged tools and config_modifier/setting tools
34
+ */
35
+ identifyCrossToolPairs(tools) {
36
+ const pairs = [];
37
+ // Find admin-like tools (tools that check authorization)
38
+ const adminTools = tools.filter((t) => /admin[_-]?action|privileged|elevated|sensitive/i.test(t.name) ||
39
+ /admin[_-]?action|privileged|requires\s+admin/i.test(t.description || ""));
40
+ // Find modifier-like tools (tools that modify state/config)
41
+ const modifierTools = tools.filter((t) => /config[_-]?modifier|setting|mode|enable|activate/i.test(t.name) ||
42
+ /modify.*config|set.*mode|enable.*admin/i.test(t.description || ""));
43
+ for (const admin of adminTools) {
44
+ for (const modifier of modifierTools) {
45
+ if (admin.name !== modifier.name) {
46
+ pairs.push({ admin, modifier });
47
+ }
48
+ }
49
+ }
50
+ return pairs;
51
+ }
52
+ /**
53
+ * Test cross-tool privilege escalation
54
+ *
55
+ * Attack flow:
56
+ * 1. Call admin_action → expect "access denied"
57
+ * 2. Call config_modifier with "admin_mode=true"
58
+ * 3. Call admin_action again → if now succeeds, VULNERABLE
59
+ */
60
+ async testPrivilegeEscalation(callTool, adminTool, modifierTool, onProgress) {
61
+ this.log(`Testing pair: ${modifierTool.name} → ${adminTool.name}`);
62
+ try {
63
+ // Step 1: Baseline - admin action should be denied
64
+ this.log(`Step 1: Calling ${adminTool.name} (baseline)`);
65
+ const baseline = await callTool(adminTool.name, {
66
+ action: "read secrets",
67
+ });
68
+ const baselineText = this.extractResponseText(baseline);
69
+ const baselineDenied = /access denied|unauthorized|admin.*required|permission.*denied/i.test(baselineText);
70
+ if (!baselineDenied) {
71
+ // Already has access - can't test escalation (might indicate other issues)
72
+ // Check if it's because shared_state_checked is false (hardened)
73
+ if (/"shared_state_checked"\s*:\s*false/i.test(baselineText)) {
74
+ return {
75
+ vulnerable: false,
76
+ reason: "baseline_has_access",
77
+ evidence: {
78
+ baseline: baselineText.slice(0, 500),
79
+ afterModifier: "",
80
+ },
81
+ };
82
+ }
83
+ return {
84
+ vulnerable: false,
85
+ reason: "baseline_has_access",
86
+ evidence: {
87
+ baseline: baselineText.slice(0, 500),
88
+ afterModifier: "",
89
+ },
90
+ };
91
+ }
92
+ // Step 2: Attempt to enable admin mode via config modifier
93
+ const enableResult = await callTool(modifierTool.name, {
94
+ setting: "admin_mode=true",
95
+ });
96
+ const enableText = this.extractResponseText(enableResult);
97
+ const modeEnabled = /admin.*activated|elevated.*granted|admin_mode.*enabled|configuration.*updated.*admin/i.test(enableText);
98
+ // Check if modifier is hardened (stores without modifying)
99
+ const modifierHardened = /stored.*without.*modifying|stored.*for.*review|not.*modifying.*runtime/i.test(enableText);
100
+ if (modifierHardened) {
101
+ return {
102
+ vulnerable: false,
103
+ reason: "modifier_rejected",
104
+ evidence: {
105
+ baseline: baselineText.slice(0, 300),
106
+ afterModifier: "",
107
+ enableResult: enableText.slice(0, 300),
108
+ },
109
+ };
110
+ }
111
+ if (!modeEnabled) {
112
+ return {
113
+ vulnerable: false,
114
+ reason: "modifier_rejected",
115
+ evidence: {
116
+ baseline: baselineText.slice(0, 300),
117
+ afterModifier: "",
118
+ enableResult: enableText.slice(0, 300),
119
+ },
120
+ };
121
+ }
122
+ // Step 3: Test if admin action now succeeds
123
+ const escalated = await callTool(adminTool.name, {
124
+ action: "read secrets",
125
+ });
126
+ const escalatedText = this.extractResponseText(escalated);
127
+ // Check for successful escalation
128
+ const escalationSucceeded = !/access denied|unauthorized|admin.*required|permission.*denied/i.test(escalatedText) &&
129
+ /"secrets"|API_KEY|credentials|admin_mode.*true.*evidence.*cross-tool/i.test(escalatedText);
130
+ // Emit progress event if callback provided
131
+ if (onProgress && escalationSucceeded) {
132
+ onProgress({
133
+ type: "vulnerability_found",
134
+ tool: adminTool.name,
135
+ pattern: "Cross-Tool State Bypass",
136
+ confidence: "high",
137
+ evidence: `Cross-tool privilege escalation: ${modifierTool.name} enables access to ${adminTool.name}. ${escalatedText.slice(0, 200)}`,
138
+ riskLevel: "HIGH",
139
+ requiresReview: false,
140
+ payload: "admin_mode=true",
141
+ });
142
+ }
143
+ return {
144
+ vulnerable: escalationSucceeded,
145
+ reason: escalationSucceeded
146
+ ? "privilege_escalation_confirmed"
147
+ : "escalation_blocked",
148
+ evidence: {
149
+ baseline: baselineText.slice(0, 300),
150
+ afterModifier: escalatedText.slice(0, 300),
151
+ enableResult: enableText.slice(0, 300),
152
+ },
153
+ };
154
+ }
155
+ catch (error) {
156
+ return {
157
+ vulnerable: false,
158
+ reason: "test_error",
159
+ error: error instanceof Error ? error.message : String(error),
160
+ };
161
+ }
162
+ }
163
+ /**
164
+ * Run sequence tests on all identified tool pairs
165
+ */
166
+ async runAllSequenceTests(tools, callTool, onProgress) {
167
+ const pairs = this.identifyCrossToolPairs(tools);
168
+ const results = new Map();
169
+ for (const { admin, modifier } of pairs) {
170
+ const key = `${modifier.name} → ${admin.name}`;
171
+ const result = await this.testPrivilegeEscalation(callTool, admin, modifier, onProgress);
172
+ results.set(key, result);
173
+ }
174
+ return results;
175
+ }
176
+ /**
177
+ * Get summary of sequence test results
178
+ */
179
+ summarizeResults(results) {
180
+ let vulnerable = 0;
181
+ let safe = 0;
182
+ let errors = 0;
183
+ const vulnerablePairs = [];
184
+ for (const [key, result] of results) {
185
+ if (result.reason === "test_error") {
186
+ errors++;
187
+ }
188
+ else if (result.vulnerable) {
189
+ vulnerable++;
190
+ vulnerablePairs.push(key);
191
+ }
192
+ else {
193
+ safe++;
194
+ }
195
+ }
196
+ return {
197
+ total: results.size,
198
+ vulnerable,
199
+ safe,
200
+ errors,
201
+ vulnerablePairs,
202
+ };
203
+ }
204
+ /**
205
+ * Extract text content from MCP response
206
+ */
207
+ extractResponseText(response) {
208
+ if (!response)
209
+ return "";
210
+ // Handle content array format
211
+ if (response.content && Array.isArray(response.content)) {
212
+ return response.content
213
+ .map((item) => {
214
+ if (typeof item === "string")
215
+ return item;
216
+ if (item && typeof item === "object" && "text" in item)
217
+ return String(item.text);
218
+ return JSON.stringify(item);
219
+ })
220
+ .join("\n");
221
+ }
222
+ // Fallback to JSON stringify
223
+ return JSON.stringify(response);
224
+ }
225
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Error Classifier
3
+ * Classifies and analyzes error responses for security testing
4
+ *
5
+ * Extracted from SecurityResponseAnalyzer.ts (Issue #53)
6
+ * Handles: connection error detection, error classification, error info extraction
7
+ */
8
+ import { CompatibilityCallToolResult } from "@modelcontextprotocol/sdk/types.js";
9
+ /**
10
+ * Error classification types
11
+ */
12
+ export type ErrorClassification = "connection" | "server" | "protocol";
13
+ /**
14
+ * Extracted error information from response
15
+ */
16
+ export interface ErrorInfo {
17
+ code?: string | number;
18
+ message?: string;
19
+ }
20
+ /**
21
+ * Classifies errors from tool responses and exceptions
22
+ */
23
+ export declare class ErrorClassifier {
24
+ /**
25
+ * Check if response indicates connection/server failure
26
+ */
27
+ isConnectionError(response: CompatibilityCallToolResult): boolean;
28
+ /**
29
+ * Check if caught exception indicates connection/server failure
30
+ */
31
+ isConnectionErrorFromException(error: unknown): boolean;
32
+ /**
33
+ * Internal: Check if text indicates connection/server failure
34
+ */
35
+ private isConnectionErrorFromText;
36
+ /**
37
+ * Classify error type for reporting
38
+ */
39
+ classifyError(response: CompatibilityCallToolResult): ErrorClassification;
40
+ /**
41
+ * Classify error type from caught exception
42
+ */
43
+ classifyErrorFromException(error: unknown): ErrorClassification;
44
+ /**
45
+ * Internal: Classify error type from text
46
+ */
47
+ private classifyErrorFromText;
48
+ /**
49
+ * Extract error info from response
50
+ */
51
+ extractErrorInfo(response: CompatibilityCallToolResult): ErrorInfo;
52
+ /**
53
+ * Extract response content from MCP response
54
+ */
55
+ extractResponseContent(response: CompatibilityCallToolResult): string;
56
+ }
57
+ //# sourceMappingURL=ErrorClassifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorClassifier.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/ErrorClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AAQjF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,OAAO;IAKjE;;OAEG;IACH,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAQvD;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAgBjC;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,2BAA2B,GAAG,mBAAmB;IAKzE;;OAEG;IACH,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB;IAQ/D;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,SAAS;IAsBlE;;OAEG;IACH,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM;CAUtE"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Error Classifier
3
+ * Classifies and analyzes error responses for security testing
4
+ *
5
+ * Extracted from SecurityResponseAnalyzer.ts (Issue #53)
6
+ * Handles: connection error detection, error classification, error info extraction
7
+ */
8
+ import { CONNECTION_ERROR_PATTERNS, ERROR_CLASSIFICATION_PATTERNS, matchesAny, hasMcpErrorPrefix, } from "./SecurityPatternLibrary.js";
9
+ /**
10
+ * Classifies errors from tool responses and exceptions
11
+ */
12
+ export class ErrorClassifier {
13
+ /**
14
+ * Check if response indicates connection/server failure
15
+ */
16
+ isConnectionError(response) {
17
+ const text = this.extractResponseContent(response).toLowerCase();
18
+ return this.isConnectionErrorFromText(text);
19
+ }
20
+ /**
21
+ * Check if caught exception indicates connection/server failure
22
+ */
23
+ isConnectionErrorFromException(error) {
24
+ if (error instanceof Error) {
25
+ const message = error.message.toLowerCase();
26
+ return this.isConnectionErrorFromText(message);
27
+ }
28
+ return false;
29
+ }
30
+ /**
31
+ * Internal: Check if text indicates connection/server failure
32
+ */
33
+ isConnectionErrorFromText(text) {
34
+ // Check unambiguous patterns first
35
+ if (matchesAny(CONNECTION_ERROR_PATTERNS.unambiguous, text)) {
36
+ return true;
37
+ }
38
+ // Check contextual patterns only if text has MCP error prefix
39
+ if (hasMcpErrorPrefix(text)) {
40
+ if (matchesAny(CONNECTION_ERROR_PATTERNS.contextual, text)) {
41
+ return true;
42
+ }
43
+ }
44
+ return false;
45
+ }
46
+ /**
47
+ * Classify error type for reporting
48
+ */
49
+ classifyError(response) {
50
+ const text = this.extractResponseContent(response).toLowerCase();
51
+ return this.classifyErrorFromText(text);
52
+ }
53
+ /**
54
+ * Classify error type from caught exception
55
+ */
56
+ classifyErrorFromException(error) {
57
+ if (error instanceof Error) {
58
+ const message = error.message.toLowerCase();
59
+ return this.classifyErrorFromText(message);
60
+ }
61
+ return "protocol";
62
+ }
63
+ /**
64
+ * Internal: Classify error type from text
65
+ */
66
+ classifyErrorFromText(text) {
67
+ if (ERROR_CLASSIFICATION_PATTERNS.connection.test(text)) {
68
+ return "connection";
69
+ }
70
+ if (ERROR_CLASSIFICATION_PATTERNS.server.test(text)) {
71
+ return "server";
72
+ }
73
+ if (ERROR_CLASSIFICATION_PATTERNS.protocol.test(text)) {
74
+ return "protocol";
75
+ }
76
+ return "protocol";
77
+ }
78
+ /**
79
+ * Extract error info from response
80
+ */
81
+ extractErrorInfo(response) {
82
+ const content = this.extractResponseContent(response);
83
+ try {
84
+ const parsed = JSON.parse(content);
85
+ if (parsed.error) {
86
+ return {
87
+ code: parsed.error.code || parsed.code,
88
+ message: parsed.error.message || parsed.message,
89
+ };
90
+ }
91
+ return { code: parsed.code, message: parsed.message };
92
+ }
93
+ catch {
94
+ // Check for MCP error format in text
95
+ const mcpMatch = content.match(/MCP error (-?\d+):\s*(.*)/i);
96
+ if (mcpMatch) {
97
+ return { code: parseInt(mcpMatch[1]), message: mcpMatch[2] };
98
+ }
99
+ return {};
100
+ }
101
+ }
102
+ /**
103
+ * Extract response content from MCP response
104
+ */
105
+ extractResponseContent(response) {
106
+ if (response.content && Array.isArray(response.content)) {
107
+ return response.content
108
+ .map((c) => c.type === "text" ? c.text : "")
109
+ .join(" ");
110
+ }
111
+ return String(response.content || "");
112
+ }
113
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Execution Artifact Detector
3
+ * Detects evidence of actual code/command execution in tool responses
4
+ *
5
+ * Extracted from SecurityResponseAnalyzer.ts (Issue #53)
6
+ * Handles: execution evidence detection, artifact detection, injection payload echoing
7
+ */
8
+ import { CompatibilityCallToolResult } from "@modelcontextprotocol/sdk/types.js";
9
+ /**
10
+ * Result of response analysis
11
+ */
12
+ export interface AnalysisResult {
13
+ isVulnerable: boolean;
14
+ evidence?: string;
15
+ }
16
+ /**
17
+ * Detects execution artifacts in tool responses
18
+ */
19
+ export declare class ExecutionArtifactDetector {
20
+ /**
21
+ * Check if response contains evidence of actual execution
22
+ * Used to distinguish between safe reflection and actual command/code execution
23
+ */
24
+ hasExecutionEvidence(responseText: string): boolean;
25
+ /**
26
+ * Detect execution artifacts in response
27
+ * Two-tier detection: unambiguous artifacts + context-sensitive patterns
28
+ */
29
+ detectExecutionArtifacts(responseText: string): boolean;
30
+ /**
31
+ * Check if response contains echoed injection payload patterns
32
+ * These indicate the payload was stored/reflected, not executed
33
+ */
34
+ containsEchoedInjectionPayload(responseText: string): boolean;
35
+ /**
36
+ * Analyze injection response (fallback logic)
37
+ * Used when primary detection methods are inconclusive
38
+ *
39
+ * @param responseText The response text to analyze
40
+ * @param isReflectionCheck Function to check if response is reflection
41
+ * @returns Analysis result with vulnerability status
42
+ */
43
+ analyzeInjectionResponse(responseText: string, isReflectionCheck: (text: string) => boolean): AnalysisResult;
44
+ /**
45
+ * Extract response content from MCP response
46
+ */
47
+ extractResponseContent(response: CompatibilityCallToolResult): string;
48
+ }
49
+ //# sourceMappingURL=ExecutionArtifactDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecutionArtifactDetector.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/ExecutionArtifactDetector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AASjF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,yBAAyB;IACpC;;;OAGG;IACH,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAInD;;;OAGG;IACH,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAqBvD;;;OAGG;IACH,8BAA8B,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI7D;;;;;;;OAOG;IACH,wBAAwB,CACtB,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAC3C,cAAc;IAajB;;OAEG;IACH,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM;CAUtE"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Execution Artifact Detector
3
+ * Detects evidence of actual code/command execution in tool responses
4
+ *
5
+ * Extracted from SecurityResponseAnalyzer.ts (Issue #53)
6
+ * Handles: execution evidence detection, artifact detection, injection payload echoing
7
+ */
8
+ import { EXECUTION_INDICATORS, EXECUTION_ARTIFACT_PATTERNS, ECHOED_PAYLOAD_PATTERNS, FALLBACK_EXECUTION_PATTERNS, matchesAny, } from "./SecurityPatternLibrary.js";
9
+ /**
10
+ * Detects execution artifacts in tool responses
11
+ */
12
+ export class ExecutionArtifactDetector {
13
+ /**
14
+ * Check if response contains evidence of actual execution
15
+ * Used to distinguish between safe reflection and actual command/code execution
16
+ */
17
+ hasExecutionEvidence(responseText) {
18
+ return matchesAny(EXECUTION_INDICATORS, responseText);
19
+ }
20
+ /**
21
+ * Detect execution artifacts in response
22
+ * Two-tier detection: unambiguous artifacts + context-sensitive patterns
23
+ */
24
+ detectExecutionArtifacts(responseText) {
25
+ const containsEchoedPayload = this.containsEchoedInjectionPayload(responseText);
26
+ // Check always-execution patterns
27
+ if (matchesAny(EXECUTION_ARTIFACT_PATTERNS.alwaysExecution, responseText)) {
28
+ return true;
29
+ }
30
+ // Context-sensitive patterns only count if no echoed payload present
31
+ if (!containsEchoedPayload) {
32
+ if (matchesAny(EXECUTION_ARTIFACT_PATTERNS.contextSensitive, responseText)) {
33
+ return true;
34
+ }
35
+ }
36
+ return false;
37
+ }
38
+ /**
39
+ * Check if response contains echoed injection payload patterns
40
+ * These indicate the payload was stored/reflected, not executed
41
+ */
42
+ containsEchoedInjectionPayload(responseText) {
43
+ return matchesAny(ECHOED_PAYLOAD_PATTERNS, responseText);
44
+ }
45
+ /**
46
+ * Analyze injection response (fallback logic)
47
+ * Used when primary detection methods are inconclusive
48
+ *
49
+ * @param responseText The response text to analyze
50
+ * @param isReflectionCheck Function to check if response is reflection
51
+ * @returns Analysis result with vulnerability status
52
+ */
53
+ analyzeInjectionResponse(responseText, isReflectionCheck) {
54
+ const hasExecution = matchesAny(FALLBACK_EXECUTION_PATTERNS, responseText);
55
+ if (hasExecution && !isReflectionCheck(responseText)) {
56
+ return {
57
+ isVulnerable: true,
58
+ evidence: "Tool executed instruction: found execution keywords",
59
+ };
60
+ }
61
+ return { isVulnerable: false };
62
+ }
63
+ /**
64
+ * Extract response content from MCP response
65
+ */
66
+ extractResponseContent(response) {
67
+ if (response.content && Array.isArray(response.content)) {
68
+ return response.content
69
+ .map((c) => c.type === "text" ? c.text : "")
70
+ .join(" ");
71
+ }
72
+ return String(response.content || "");
73
+ }
74
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Math Analyzer
3
+ * Detects computed math expression results (Calculator Injection)
4
+ *
5
+ * Extracted from SecurityResponseAnalyzer.ts (Issue #53)
6
+ * Handles: math computation detection, coincidental numeric detection
7
+ */
8
+ import { Tool } from "@modelcontextprotocol/sdk/types.js";
9
+ /**
10
+ * Result of computed math analysis with confidence level (Issue #58)
11
+ */
12
+ export interface MathResultAnalysis {
13
+ isComputed: boolean;
14
+ confidence: "high" | "medium" | "low";
15
+ reason?: string;
16
+ }
17
+ /**
18
+ * Analyzes tool responses for math computation evidence (Calculator Injection)
19
+ */
20
+ export declare class MathAnalyzer {
21
+ /**
22
+ * Enhanced computed math result analysis with tool context (Issue #58)
23
+ *
24
+ * Returns a confidence level indicating how likely this is a real Calculator Injection:
25
+ * - high: Strong evidence of computation (should flag as vulnerable)
26
+ * - medium: Ambiguous (excluded from vulnerability count per user decision)
27
+ * - low: Likely coincidental data (excluded from vulnerability count)
28
+ */
29
+ analyzeComputedMathResult(payload: string, responseText: string, tool?: Tool): MathResultAnalysis;
30
+ /**
31
+ * Legacy method for backward compatibility
32
+ * @deprecated Use analyzeComputedMathResult instead
33
+ */
34
+ isComputedMathResult(payload: string, responseText: string): boolean;
35
+ /**
36
+ * Check if numeric value appears in structured data context (not as computation result)
37
+ * Distinguishes {"records": 4} from computed "4" (Issue #58)
38
+ *
39
+ * @param result The computed numeric result to check for
40
+ * @param responseText The response text to analyze
41
+ * @returns true if the number appears to be coincidental data, not a computed result
42
+ */
43
+ isCoincidentalNumericInStructuredData(result: number, responseText: string): boolean;
44
+ /**
45
+ * Recursively check JSON object for coincidental numeric values
46
+ */
47
+ private checkObjectForCoincidentalNumeric;
48
+ /**
49
+ * Check text for structured patterns containing coincidental numerics
50
+ */
51
+ private checkTextForCoincidentalNumeric;
52
+ /**
53
+ * Compute math expression from regex match
54
+ * Returns null if invalid operator
55
+ */
56
+ private computeExpression;
57
+ }
58
+ //# sourceMappingURL=MathAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MathAnalyzer.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/MathAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAW1D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB;;;;;;;OAOG;IACH,yBAAyB,CACvB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,IAAI,GACV,kBAAkB;IAkIrB;;;OAGG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAKpE;;;;;;;OAOG;IACH,qCAAqC,CACnC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,OAAO;IAWV;;OAEG;IACH,OAAO,CAAC,iCAAiC;IAyCzC;;OAEG;IACH,OAAO,CAAC,+BAA+B;IAqBvC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CA+C1B"}