@bryan-thompson/inspector-assessment-client 1.25.4 → 1.25.5

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 (123) hide show
  1. package/dist/assets/{OAuthCallback-DE62cdTZ.js → OAuthCallback-Dl4GYls3.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-CWjFdCIE.js → OAuthDebugCallback-BdJ38Z-r.js} +1 -1
  3. package/dist/assets/{index-Df9Sx1jt.css → index-cHhcEXbr.css} +4 -0
  4. package/dist/assets/{index-PCQVSwHa.js → index-pfUiTdQb.js} +4 -4
  5. package/dist/index.html +2 -2
  6. package/lib/lib/assessment/coreTypes.d.ts +65 -0
  7. package/lib/lib/assessment/coreTypes.d.ts.map +1 -1
  8. package/lib/lib/assessment/extendedTypes.d.ts +127 -0
  9. package/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
  10. package/lib/lib/assessment/resultTypes.d.ts +45 -0
  11. package/lib/lib/assessment/resultTypes.d.ts.map +1 -1
  12. package/lib/services/assessment/AssessmentOrchestrator.d.ts +3 -7
  13. package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
  14. package/lib/services/assessment/AssessmentOrchestrator.js +13 -2
  15. package/lib/services/assessment/TestDataGenerator.d.ts +9 -1
  16. package/lib/services/assessment/TestDataGenerator.d.ts.map +1 -1
  17. package/lib/services/assessment/TestDataGenerator.js +32 -6
  18. package/lib/services/assessment/TestScenarioEngine.d.ts +9 -1
  19. package/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -1
  20. package/lib/services/assessment/TestScenarioEngine.js +17 -14
  21. package/lib/services/assessment/config/annotationPatterns.d.ts +3 -1
  22. package/lib/services/assessment/config/annotationPatterns.d.ts.map +1 -1
  23. package/lib/services/assessment/config/annotationPatterns.js +5 -2
  24. package/lib/services/assessment/config/architecturePatterns.d.ts +101 -0
  25. package/lib/services/assessment/config/architecturePatterns.d.ts.map +1 -0
  26. package/lib/services/assessment/config/architecturePatterns.js +248 -0
  27. package/lib/services/assessment/config/performanceConfig.d.ts +122 -0
  28. package/lib/services/assessment/config/performanceConfig.d.ts.map +1 -0
  29. package/lib/services/assessment/config/performanceConfig.js +154 -0
  30. package/lib/services/assessment/config/sanitizationPatterns.d.ts +63 -0
  31. package/lib/services/assessment/config/sanitizationPatterns.d.ts.map +1 -0
  32. package/lib/services/assessment/config/sanitizationPatterns.js +223 -0
  33. package/lib/services/assessment/lib/claudeCodeBridge.d.ts +3 -1
  34. package/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -1
  35. package/lib/services/assessment/lib/claudeCodeBridge.js +5 -3
  36. package/lib/services/assessment/lib/concurrencyLimit.d.ts +6 -2
  37. package/lib/services/assessment/lib/concurrencyLimit.d.ts.map +1 -1
  38. package/lib/services/assessment/lib/concurrencyLimit.js +13 -6
  39. package/lib/services/assessment/lib/errors.d.ts +90 -0
  40. package/lib/services/assessment/lib/errors.d.ts.map +1 -0
  41. package/lib/services/assessment/lib/errors.js +136 -0
  42. package/lib/services/assessment/lib/timeoutUtils.d.ts +69 -0
  43. package/lib/services/assessment/lib/timeoutUtils.d.ts.map +1 -0
  44. package/lib/services/assessment/lib/timeoutUtils.js +103 -0
  45. package/lib/services/assessment/modules/BaseAssessor.d.ts +43 -8
  46. package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -1
  47. package/lib/services/assessment/modules/BaseAssessor.js +103 -34
  48. package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts +38 -1
  49. package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts.map +1 -1
  50. package/lib/services/assessment/modules/DeveloperExperienceAssessor.js +185 -19
  51. package/lib/services/assessment/modules/DocumentationAssessor.d.ts +5 -0
  52. package/lib/services/assessment/modules/DocumentationAssessor.d.ts.map +1 -1
  53. package/lib/services/assessment/modules/DocumentationAssessor.js +11 -0
  54. package/lib/services/assessment/modules/ErrorHandlingAssessor.js +1 -1
  55. package/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -1
  56. package/lib/services/assessment/modules/FunctionalityAssessor.js +6 -3
  57. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts +3 -0
  58. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -1
  59. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +14 -2
  60. package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
  61. package/lib/services/assessment/modules/ManifestValidationAssessor.js +7 -2
  62. package/lib/services/assessment/modules/PromptAssessor.d.ts +1 -0
  63. package/lib/services/assessment/modules/PromptAssessor.d.ts.map +1 -1
  64. package/lib/services/assessment/modules/PromptAssessor.js +26 -16
  65. package/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
  66. package/lib/services/assessment/modules/ProtocolComplianceAssessor.js +6 -2
  67. package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts +5 -0
  68. package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts.map +1 -1
  69. package/lib/services/assessment/modules/ProtocolConformanceAssessor.js +15 -0
  70. package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
  71. package/lib/services/assessment/modules/ResourceAssessor.js +8 -2
  72. package/lib/services/assessment/modules/SecurityAssessor.d.ts +3 -171
  73. package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
  74. package/lib/services/assessment/modules/SecurityAssessor.js +25 -1480
  75. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +27 -28
  76. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
  77. package/lib/services/assessment/modules/ToolAnnotationAssessor.js +340 -863
  78. package/lib/services/assessment/modules/UsabilityAssessor.d.ts +5 -0
  79. package/lib/services/assessment/modules/UsabilityAssessor.d.ts.map +1 -1
  80. package/lib/services/assessment/modules/UsabilityAssessor.js +11 -0
  81. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts +57 -0
  82. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts.map +1 -0
  83. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.js +176 -0
  84. package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts +67 -0
  85. package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts.map +1 -0
  86. package/lib/services/assessment/modules/annotations/ArchitectureDetector.js +239 -0
  87. package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts +46 -0
  88. package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts.map +1 -0
  89. package/lib/services/assessment/modules/annotations/BehaviorInference.js +394 -0
  90. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts +64 -0
  91. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts.map +1 -0
  92. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.js +304 -0
  93. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts +43 -0
  94. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -0
  95. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +276 -0
  96. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts +122 -0
  97. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts.map +1 -0
  98. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.js +388 -0
  99. package/lib/services/assessment/modules/annotations/index.d.ts +13 -0
  100. package/lib/services/assessment/modules/annotations/index.d.ts.map +1 -0
  101. package/lib/services/assessment/modules/annotations/index.js +15 -0
  102. package/lib/services/assessment/modules/index.d.ts +10 -0
  103. package/lib/services/assessment/modules/index.d.ts.map +1 -1
  104. package/lib/services/assessment/modules/index.js +13 -0
  105. package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts +125 -0
  106. package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts.map +1 -0
  107. package/lib/services/assessment/modules/securityTests/SanitizationDetector.js +345 -0
  108. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts +33 -0
  109. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -0
  110. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +128 -0
  111. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts +67 -0
  112. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -0
  113. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +372 -0
  114. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +178 -0
  115. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -0
  116. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +1207 -0
  117. package/lib/services/assessment/modules/securityTests/index.d.ts +8 -0
  118. package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -0
  119. package/lib/services/assessment/modules/securityTests/index.js +7 -0
  120. package/lib/services/assessment/tool-classifier-patterns.d.ts +1 -0
  121. package/lib/services/assessment/tool-classifier-patterns.d.ts.map +1 -1
  122. package/lib/services/assessment/tool-classifier-patterns.js +17 -0
  123. package/package.json +1 -1
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Security Payload Tester
3
+ * Executes security tests with payloads against MCP tools
4
+ *
5
+ * Extracted from SecurityAssessor.ts for maintainability.
6
+ * Handles test execution, batching, and progress tracking.
7
+ */
8
+ import { SecurityTestResult } from "../../../../lib/assessmentTypes.js";
9
+ import { ProgressCallback } from "../../../../lib/assessment/progressTypes.js";
10
+ import { CompatibilityCallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
11
+ import { SecurityPayload } from "../../../../lib/securityPatterns.js";
12
+ /**
13
+ * Re-export ProgressCallback for external use
14
+ */
15
+ export type TestProgressCallback = ProgressCallback;
16
+ /**
17
+ * Configuration for payload testing
18
+ */
19
+ export interface PayloadTestConfig {
20
+ enableDomainTesting?: boolean;
21
+ maxParallelTests?: number;
22
+ securityTestTimeout?: number;
23
+ selectedToolsForTesting?: string[];
24
+ }
25
+ /**
26
+ * Logger interface for test execution
27
+ */
28
+ export interface TestLogger {
29
+ log: (message: string) => void;
30
+ logError: (message: string, error: unknown) => void;
31
+ }
32
+ /**
33
+ * Executes security tests with payloads against MCP tools
34
+ */
35
+ export declare class SecurityPayloadTester {
36
+ private config;
37
+ private logger;
38
+ private executeWithTimeout;
39
+ private responseAnalyzer;
40
+ private payloadGenerator;
41
+ private sanitizationDetector;
42
+ private testCount;
43
+ constructor(config: PayloadTestConfig, logger: TestLogger, executeWithTimeout: <T>(promise: Promise<T>, timeout: number) => Promise<T>);
44
+ /**
45
+ * Run comprehensive security tests (advanced mode)
46
+ * Tests selected tools with ALL 23 security patterns using diverse payloads
47
+ */
48
+ runUniversalSecurityTests(tools: Tool[], callTool: (name: string, params: Record<string, unknown>) => Promise<CompatibilityCallToolResult>, onProgress?: TestProgressCallback): Promise<SecurityTestResult[]>;
49
+ /**
50
+ * Run basic security tests (fast mode)
51
+ * Tests only 5 critical injection patterns with 1 generic payload each
52
+ */
53
+ runBasicSecurityTests(tools: Tool[], callTool: (name: string, params: Record<string, unknown>) => Promise<CompatibilityCallToolResult>, onProgress?: TestProgressCallback): Promise<SecurityTestResult[]>;
54
+ /**
55
+ * Test tool with a specific payload
56
+ */
57
+ testPayload(tool: Tool, attackName: string, payload: SecurityPayload, callTool: (name: string, params: Record<string, unknown>) => Promise<CompatibilityCallToolResult>): Promise<SecurityTestResult>;
58
+ /**
59
+ * Extract error message from caught exception
60
+ */
61
+ private extractErrorMessage;
62
+ /**
63
+ * Sleep for specified milliseconds
64
+ */
65
+ private sleep;
66
+ }
67
+ //# sourceMappingURL=SecurityPayloadTester.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurityPayloadTester.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/SecurityPayloadTester.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,gBAAgB,EAGjB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,2BAA2B,EAC3B,IAAI,EACL,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAGL,eAAe,EAChB,MAAM,wBAAwB,CAAC;AAOhC;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD;AAED;;GAEG;AACH,qBAAa,qBAAqB;IAO9B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,kBAAkB;IAR5B,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,SAAS,CAAK;gBAGZ,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,UAAU,EAClB,kBAAkB,EAAE,CAAC,CAAC,EAC5B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,CAAC,CAAC;IAOjB;;;OAGG;IACG,yBAAyB,CAC7B,KAAK,EAAE,IAAI,EAAE,EACb,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,2BAA2B,CAAC,EACzC,UAAU,CAAC,EAAE,oBAAoB,GAChC,OAAO,CAAC,kBAAkB,EAAE,CAAC;IA2JhC;;;OAGG;IACG,qBAAqB,CACzB,KAAK,EAAE,IAAI,EAAE,EACb,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,2BAA2B,CAAC,EACzC,UAAU,CAAC,EAAE,oBAAoB,GAChC,OAAO,CAAC,kBAAkB,EAAE,CAAC;IA8IhC;;OAEG;IACG,WAAW,CACf,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,2BAA2B,CAAC,GACxC,OAAO,CAAC,kBAAkB,CAAC;IAuI9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd"}
@@ -0,0 +1,372 @@
1
+ /**
2
+ * Security Payload Tester
3
+ * Executes security tests with payloads against MCP tools
4
+ *
5
+ * Extracted from SecurityAssessor.ts for maintainability.
6
+ * Handles test execution, batching, and progress tracking.
7
+ */
8
+ import { getAllAttackPatterns, getPayloadsForAttack, } from "../../../../lib/securityPatterns.js";
9
+ import { createConcurrencyLimit } from "../../lib/concurrencyLimit.js";
10
+ import { SecurityResponseAnalyzer } from "./SecurityResponseAnalyzer.js";
11
+ import { SecurityPayloadGenerator } from "./SecurityPayloadGenerator.js";
12
+ import { SanitizationDetector } from "./SanitizationDetector.js";
13
+ import { DEFAULT_PERFORMANCE_CONFIG } from "../../config/performanceConfig.js";
14
+ /**
15
+ * Executes security tests with payloads against MCP tools
16
+ */
17
+ export class SecurityPayloadTester {
18
+ config;
19
+ logger;
20
+ executeWithTimeout;
21
+ responseAnalyzer;
22
+ payloadGenerator;
23
+ sanitizationDetector;
24
+ testCount = 0;
25
+ constructor(config, logger, executeWithTimeout) {
26
+ this.config = config;
27
+ this.logger = logger;
28
+ this.executeWithTimeout = executeWithTimeout;
29
+ this.responseAnalyzer = new SecurityResponseAnalyzer();
30
+ this.payloadGenerator = new SecurityPayloadGenerator();
31
+ this.sanitizationDetector = new SanitizationDetector();
32
+ }
33
+ /**
34
+ * Run comprehensive security tests (advanced mode)
35
+ * Tests selected tools with ALL 23 security patterns using diverse payloads
36
+ */
37
+ async runUniversalSecurityTests(tools, callTool, onProgress) {
38
+ // Check if advanced security testing is enabled
39
+ if (!this.config.enableDomainTesting) {
40
+ return this.runBasicSecurityTests(tools, callTool, onProgress);
41
+ }
42
+ const results = [];
43
+ const attackPatterns = getAllAttackPatterns();
44
+ // Parallel tool testing with concurrency limit
45
+ const concurrency = this.config.maxParallelTests ?? 5;
46
+ const limit = createConcurrencyLimit(concurrency);
47
+ // Progress tracking for batched events
48
+ // Uses centralized PerformanceConfig values (Issue #37)
49
+ let totalPayloads = 0;
50
+ for (const pattern of attackPatterns) {
51
+ totalPayloads += getPayloadsForAttack(pattern.attackName).length;
52
+ }
53
+ const totalEstimate = tools.length * totalPayloads;
54
+ let completedTests = 0;
55
+ let lastBatchTime = Date.now();
56
+ const startTime = Date.now();
57
+ const BATCH_INTERVAL = DEFAULT_PERFORMANCE_CONFIG.batchFlushIntervalMs;
58
+ const BATCH_SIZE = DEFAULT_PERFORMANCE_CONFIG.securityBatchSize;
59
+ let batchCount = 0;
60
+ const emitProgressBatch = () => {
61
+ if (onProgress) {
62
+ const event = {
63
+ type: "test_batch",
64
+ module: "security",
65
+ completed: completedTests,
66
+ total: totalEstimate,
67
+ batchSize: batchCount,
68
+ elapsed: Date.now() - startTime,
69
+ };
70
+ onProgress(event);
71
+ }
72
+ batchCount = 0;
73
+ lastBatchTime = Date.now();
74
+ };
75
+ this.logger.log(`Starting ADVANCED security assessment - testing ${tools.length} tools with ${attackPatterns.length} security patterns (~${totalEstimate} tests) [concurrency: ${concurrency}]`);
76
+ const allToolResults = await Promise.all(tools.map((tool) => limit(async () => {
77
+ const toolResults = [];
78
+ // Tools with no input parameters can't be exploited
79
+ if (!this.payloadGenerator.hasInputParameters(tool)) {
80
+ this.logger.log(`${tool.name} has no input parameters - adding passing results`);
81
+ for (const attackPattern of attackPatterns) {
82
+ const payloads = getPayloadsForAttack(attackPattern.attackName);
83
+ for (const payload of payloads) {
84
+ toolResults.push({
85
+ testName: attackPattern.attackName,
86
+ description: payload.description,
87
+ payload: payload.payload,
88
+ riskLevel: payload.riskLevel,
89
+ toolName: tool.name,
90
+ vulnerable: false,
91
+ evidence: "Tool has no input parameters - cannot be exploited via payload injection",
92
+ });
93
+ }
94
+ }
95
+ return toolResults;
96
+ }
97
+ this.logger.log(`Testing ${tool.name} with all attack patterns`);
98
+ for (const attackPattern of attackPatterns) {
99
+ const payloads = getPayloadsForAttack(attackPattern.attackName);
100
+ for (const payload of payloads) {
101
+ this.testCount++;
102
+ completedTests++;
103
+ batchCount++;
104
+ try {
105
+ const result = await this.testPayload(tool, attackPattern.attackName, payload, callTool);
106
+ toolResults.push(result);
107
+ if (result.vulnerable && onProgress) {
108
+ this.logger.log(`🚨 VULNERABILITY: ${tool.name} - ${attackPattern.attackName} (${payload.payloadType}: ${payload.description})`);
109
+ const vulnEvent = {
110
+ type: "vulnerability_found",
111
+ tool: tool.name,
112
+ pattern: attackPattern.attackName,
113
+ confidence: result.confidence || "medium",
114
+ evidence: result.evidence || "Vulnerability detected",
115
+ riskLevel: payload.riskLevel,
116
+ requiresReview: result.requiresManualReview || false,
117
+ payload: payload.payload,
118
+ };
119
+ onProgress(vulnEvent);
120
+ }
121
+ }
122
+ catch (error) {
123
+ this.logger.logError(`Error testing ${tool.name} with ${attackPattern.attackName}`, error);
124
+ }
125
+ const timeSinceLastBatch = Date.now() - lastBatchTime;
126
+ if (batchCount >= BATCH_SIZE ||
127
+ timeSinceLastBatch >= BATCH_INTERVAL) {
128
+ emitProgressBatch();
129
+ }
130
+ if (this.testCount % 5 === 0) {
131
+ await this.sleep(100);
132
+ }
133
+ }
134
+ }
135
+ return toolResults;
136
+ })));
137
+ for (const toolResults of allToolResults) {
138
+ results.push(...toolResults);
139
+ }
140
+ if (batchCount > 0) {
141
+ emitProgressBatch();
142
+ }
143
+ this.logger.log(`ADVANCED security assessment complete: ${results.length} tests executed, ${results.filter((r) => r.vulnerable).length} vulnerabilities found`);
144
+ return results;
145
+ }
146
+ /**
147
+ * Run basic security tests (fast mode)
148
+ * Tests only 5 critical injection patterns with 1 generic payload each
149
+ */
150
+ async runBasicSecurityTests(tools, callTool, onProgress) {
151
+ const results = [];
152
+ const criticalPatterns = [
153
+ "Command Injection",
154
+ "Calculator Injection",
155
+ "SQL Injection",
156
+ "Path Traversal",
157
+ "Unicode Bypass",
158
+ ];
159
+ const allPatterns = getAllAttackPatterns();
160
+ const basicPatterns = allPatterns.filter((p) => criticalPatterns.includes(p.attackName));
161
+ // Progress tracking for batched events
162
+ // Uses centralized PerformanceConfig values (Issue #37)
163
+ const totalEstimate = tools.length * basicPatterns.length;
164
+ let completedTests = 0;
165
+ let lastBatchTime = Date.now();
166
+ const startTime = Date.now();
167
+ const BATCH_INTERVAL = DEFAULT_PERFORMANCE_CONFIG.batchFlushIntervalMs;
168
+ const BATCH_SIZE = DEFAULT_PERFORMANCE_CONFIG.securityBatchSize;
169
+ let batchCount = 0;
170
+ const emitProgressBatch = () => {
171
+ if (onProgress) {
172
+ const event = {
173
+ type: "test_batch",
174
+ module: "security",
175
+ completed: completedTests,
176
+ total: totalEstimate,
177
+ batchSize: batchCount,
178
+ elapsed: Date.now() - startTime,
179
+ };
180
+ onProgress(event);
181
+ }
182
+ batchCount = 0;
183
+ lastBatchTime = Date.now();
184
+ };
185
+ this.logger.log(`Starting BASIC security assessment - testing ${tools.length} tools with ${basicPatterns.length} critical injection patterns (~${totalEstimate} tests)`);
186
+ for (const tool of tools) {
187
+ if (!this.payloadGenerator.hasInputParameters(tool)) {
188
+ this.logger.log(`${tool.name} has no input parameters - adding passing results`);
189
+ for (const attackPattern of basicPatterns) {
190
+ const allPayloads = getPayloadsForAttack(attackPattern.attackName);
191
+ const payload = allPayloads[0];
192
+ if (payload) {
193
+ results.push({
194
+ testName: attackPattern.attackName,
195
+ description: payload.description,
196
+ payload: payload.payload,
197
+ riskLevel: payload.riskLevel,
198
+ toolName: tool.name,
199
+ vulnerable: false,
200
+ evidence: "Tool has no input parameters - cannot be exploited via payload injection",
201
+ });
202
+ }
203
+ }
204
+ continue;
205
+ }
206
+ this.logger.log(`Testing ${tool.name} with ${basicPatterns.length} critical patterns`);
207
+ for (const attackPattern of basicPatterns) {
208
+ const allPayloads = getPayloadsForAttack(attackPattern.attackName);
209
+ const payload = allPayloads[0];
210
+ if (!payload)
211
+ continue;
212
+ this.testCount++;
213
+ completedTests++;
214
+ batchCount++;
215
+ try {
216
+ const result = await this.testPayload(tool, attackPattern.attackName, payload, callTool);
217
+ results.push(result);
218
+ if (result.vulnerable && onProgress) {
219
+ this.logger.log(`🚨 VULNERABILITY: ${tool.name} - ${attackPattern.attackName}`);
220
+ const vulnEvent = {
221
+ type: "vulnerability_found",
222
+ tool: tool.name,
223
+ pattern: attackPattern.attackName,
224
+ confidence: result.confidence || "medium",
225
+ evidence: result.evidence || "Vulnerability detected",
226
+ riskLevel: payload.riskLevel,
227
+ requiresReview: result.requiresManualReview || false,
228
+ payload: payload.payload,
229
+ };
230
+ onProgress(vulnEvent);
231
+ }
232
+ }
233
+ catch (error) {
234
+ this.logger.logError(`Error testing ${tool.name} with ${attackPattern.attackName}`, error);
235
+ }
236
+ const timeSinceLastBatch = Date.now() - lastBatchTime;
237
+ if (batchCount >= BATCH_SIZE || timeSinceLastBatch >= BATCH_INTERVAL) {
238
+ emitProgressBatch();
239
+ }
240
+ if (this.testCount % 5 === 0) {
241
+ await this.sleep(100);
242
+ }
243
+ }
244
+ }
245
+ if (batchCount > 0) {
246
+ emitProgressBatch();
247
+ }
248
+ this.logger.log(`BASIC security assessment complete: ${results.length} tests executed, ${results.filter((r) => r.vulnerable).length} vulnerabilities found`);
249
+ return results;
250
+ }
251
+ /**
252
+ * Test tool with a specific payload
253
+ */
254
+ async testPayload(tool, attackName, payload, callTool) {
255
+ // Skip execution-based tests for API wrappers
256
+ if (this.payloadGenerator.isApiWrapper(tool) &&
257
+ this.payloadGenerator.isExecutionTest(attackName)) {
258
+ return {
259
+ testName: attackName,
260
+ description: payload.description,
261
+ payload: payload.payload,
262
+ riskLevel: payload.riskLevel,
263
+ toolName: tool.name,
264
+ vulnerable: false,
265
+ evidence: "API wrapper tool - skips execution tests (returns external data as text, does not execute it as code)",
266
+ };
267
+ }
268
+ try {
269
+ const params = this.payloadGenerator.createTestParameters(payload, tool);
270
+ if (Object.keys(params).length === 0) {
271
+ return {
272
+ testName: attackName,
273
+ description: payload.description,
274
+ payload: payload.payload,
275
+ riskLevel: payload.riskLevel,
276
+ toolName: tool.name,
277
+ vulnerable: false,
278
+ evidence: "No compatible parameters for testing",
279
+ };
280
+ }
281
+ // Use config timeout or fall back to centralized PerformanceConfig (Issue #37)
282
+ const securityTimeout = this.config.securityTestTimeout ??
283
+ DEFAULT_PERFORMANCE_CONFIG.securityTestTimeoutMs;
284
+ const response = await this.executeWithTimeout(callTool(tool.name, params), securityTimeout);
285
+ // Check for connection errors FIRST
286
+ if (this.responseAnalyzer.isConnectionError(response)) {
287
+ return {
288
+ testName: attackName,
289
+ description: payload.description,
290
+ payload: payload.payload,
291
+ riskLevel: payload.riskLevel,
292
+ toolName: tool.name,
293
+ vulnerable: true,
294
+ evidence: `CONNECTION ERROR: Test could not complete due to server/network failure`,
295
+ response: this.responseAnalyzer.extractResponseContent(response),
296
+ connectionError: true,
297
+ errorType: this.responseAnalyzer.classifyError(response),
298
+ testReliability: "failed",
299
+ confidence: "high",
300
+ requiresManualReview: true,
301
+ };
302
+ }
303
+ // Analyze with evidence-based detection
304
+ const { isVulnerable, evidence } = this.responseAnalyzer.analyzeResponse(response, payload, tool);
305
+ // Issue #56: Detect sanitization for false positive reduction
306
+ const responseText = this.responseAnalyzer.extractResponseContent(response);
307
+ const toolSanitization = this.sanitizationDetector.detect(tool);
308
+ const responseSanitization = this.sanitizationDetector.detectInResponse(responseText);
309
+ const combinedSanitization = this.sanitizationDetector.mergeResults(toolSanitization, responseSanitization);
310
+ // Calculate confidence with sanitization awareness
311
+ const confidenceResult = this.responseAnalyzer.calculateConfidence(tool, isVulnerable, evidence || "", responseText, payload, combinedSanitization);
312
+ return {
313
+ testName: attackName,
314
+ description: payload.description,
315
+ payload: payload.payload,
316
+ riskLevel: payload.riskLevel,
317
+ toolName: tool.name,
318
+ vulnerable: isVulnerable,
319
+ evidence,
320
+ response: responseText,
321
+ // Issue #56: Include sanitization info for transparency
322
+ sanitizationDetected: combinedSanitization.detected,
323
+ sanitizationLibraries: combinedSanitization.libraries,
324
+ ...confidenceResult,
325
+ };
326
+ }
327
+ catch (error) {
328
+ // Check if error is a connection/server failure
329
+ if (this.responseAnalyzer.isConnectionErrorFromException(error)) {
330
+ return {
331
+ testName: attackName,
332
+ description: payload.description,
333
+ payload: payload.payload,
334
+ riskLevel: payload.riskLevel,
335
+ toolName: tool.name,
336
+ vulnerable: false,
337
+ evidence: `CONNECTION ERROR: Test could not complete due to server/network failure`,
338
+ response: this.extractErrorMessage(error),
339
+ connectionError: true,
340
+ errorType: this.responseAnalyzer.classifyErrorFromException(error),
341
+ testReliability: "failed",
342
+ confidence: "high",
343
+ requiresManualReview: true,
344
+ };
345
+ }
346
+ return {
347
+ testName: attackName,
348
+ description: payload.description,
349
+ payload: payload.payload,
350
+ riskLevel: payload.riskLevel,
351
+ toolName: tool.name,
352
+ vulnerable: false,
353
+ evidence: `Tool rejected input: ${this.extractErrorMessage(error)}`,
354
+ };
355
+ }
356
+ }
357
+ /**
358
+ * Extract error message from caught exception
359
+ */
360
+ extractErrorMessage(error) {
361
+ if (error instanceof Error) {
362
+ return error.message;
363
+ }
364
+ return String(error);
365
+ }
366
+ /**
367
+ * Sleep for specified milliseconds
368
+ */
369
+ sleep(ms) {
370
+ return new Promise((resolve) => setTimeout(resolve, ms));
371
+ }
372
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Security Response Analyzer
3
+ * Analyzes tool responses for evidence-based vulnerability detection
4
+ *
5
+ * Extracted from SecurityAssessor.ts for maintainability.
6
+ * Handles response analysis, reflection detection, and confidence calculation.
7
+ */
8
+ import { CompatibilityCallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
9
+ import { SecurityPayload } from "../../../../lib/securityPatterns.js";
10
+ import type { SanitizationDetectionResult } from "./SanitizationDetector.js";
11
+ /**
12
+ * Result of confidence calculation
13
+ */
14
+ export interface ConfidenceResult {
15
+ confidence: "high" | "medium" | "low";
16
+ requiresManualReview: boolean;
17
+ manualReviewReason?: string;
18
+ reviewGuidance?: string;
19
+ }
20
+ /**
21
+ * Result of response analysis
22
+ */
23
+ export interface AnalysisResult {
24
+ isVulnerable: boolean;
25
+ evidence?: string;
26
+ }
27
+ /**
28
+ * Result of computed math analysis with confidence level (Issue #58)
29
+ */
30
+ export interface MathResultAnalysis {
31
+ isComputed: boolean;
32
+ confidence: "high" | "medium" | "low";
33
+ reason?: string;
34
+ }
35
+ /**
36
+ * Error classification types
37
+ */
38
+ export type ErrorClassification = "connection" | "server" | "protocol";
39
+ /**
40
+ * Analyzes tool responses for security vulnerabilities
41
+ * Distinguishes between safe reflection and actual execution
42
+ */
43
+ export declare class SecurityResponseAnalyzer {
44
+ /**
45
+ * Analyze response with evidence-based detection
46
+ * CRITICAL: Distinguish between safe reflection and actual execution
47
+ *
48
+ * Refactored to reduce cyclomatic complexity (Issue #36).
49
+ * Detection flow: Error checks → Tool behavior → Evidence matching
50
+ */
51
+ analyzeResponse(response: CompatibilityCallToolResult, payload: SecurityPayload, tool: Tool): AnalysisResult;
52
+ /**
53
+ * Check for safe error responses that indicate proper input rejection
54
+ * Handles: MCP validation errors (-32602), HTTP 4xx/5xx errors
55
+ */
56
+ private checkSafeErrorResponses;
57
+ /**
58
+ * Check for safe tool behavior patterns
59
+ * Handles: Tool categories, reflection, computed math, validation rejection
60
+ */
61
+ private checkSafeToolBehavior;
62
+ /**
63
+ * Check for vulnerability evidence in response
64
+ * Handles: Evidence pattern matching, fallback injection analysis
65
+ */
66
+ private checkVulnerabilityEvidence;
67
+ /**
68
+ * Check if tool explicitly rejected input with validation error (SAFE)
69
+ */
70
+ isValidationRejection(response: CompatibilityCallToolResult): boolean;
71
+ /**
72
+ * Check if response is an MCP validation error (safe rejection)
73
+ */
74
+ isMCPValidationError(errorInfo: {
75
+ code?: string | number;
76
+ message?: string;
77
+ }, responseText: string): boolean;
78
+ /**
79
+ * Check if response is an HTTP error (Issue #26)
80
+ */
81
+ isHttpErrorResponse(responseText: string): boolean;
82
+ /**
83
+ * Check if evidence pattern is ambiguous
84
+ */
85
+ isValidationPattern(evidencePattern: RegExp): boolean;
86
+ /**
87
+ * Check if response contains evidence of actual execution
88
+ */
89
+ hasExecutionEvidence(responseText: string): boolean;
90
+ /**
91
+ * Check if a math expression payload was computed (execution evidence)
92
+ */
93
+ isComputedMathResult(payload: string, responseText: string): boolean;
94
+ /**
95
+ * Check if numeric value appears in structured data context (not as computation result)
96
+ * Distinguishes {"records": 4} from computed "4" (Issue #58)
97
+ *
98
+ * @param result The computed numeric result to check for
99
+ * @param responseText The response text to analyze
100
+ * @returns true if the number appears to be coincidental data, not a computed result
101
+ */
102
+ isCoincidentalNumericInStructuredData(result: number, responseText: string): boolean;
103
+ /**
104
+ * Enhanced computed math result analysis with tool context (Issue #58)
105
+ *
106
+ * Returns a confidence level indicating how likely this is a real Calculator Injection:
107
+ * - high: Strong evidence of computation (should flag as vulnerable)
108
+ * - medium: Ambiguous (excluded from vulnerability count per user decision)
109
+ * - low: Likely coincidental data (excluded from vulnerability count)
110
+ */
111
+ analyzeComputedMathResult(payload: string, responseText: string, tool?: Tool): MathResultAnalysis;
112
+ /**
113
+ * Check if response indicates connection/server failure
114
+ */
115
+ isConnectionError(response: CompatibilityCallToolResult): boolean;
116
+ /**
117
+ * Check if caught exception indicates connection/server failure
118
+ */
119
+ isConnectionErrorFromException(error: unknown): boolean;
120
+ /**
121
+ * Classify error type for reporting
122
+ */
123
+ classifyError(response: CompatibilityCallToolResult): ErrorClassification;
124
+ /**
125
+ * Classify error type from caught exception
126
+ */
127
+ classifyErrorFromException(error: unknown): ErrorClassification;
128
+ /**
129
+ * Check if response is just reflection (safe)
130
+ * Two-layer defense: Match reflection patterns, verify NO execution evidence
131
+ */
132
+ isReflectionResponse(responseText: string): boolean;
133
+ /**
134
+ * Detect execution artifacts in response
135
+ */
136
+ detectExecutionArtifacts(responseText: string): boolean;
137
+ /**
138
+ * Check if response contains echoed injection payload patterns
139
+ */
140
+ containsEchoedInjectionPayload(responseText: string): boolean;
141
+ /**
142
+ * Analyze injection response (fallback logic)
143
+ */
144
+ analyzeInjectionResponse(response: CompatibilityCallToolResult, _payload: string): AnalysisResult;
145
+ /**
146
+ * Calculate confidence level and manual review requirements
147
+ *
148
+ * @param tool - The tool being tested
149
+ * @param isVulnerable - Whether the tool was flagged as vulnerable
150
+ * @param evidence - Evidence string from vulnerability detection
151
+ * @param responseText - The response text from the tool
152
+ * @param payload - The security payload used for testing
153
+ * @param sanitizationResult - Optional sanitization detection result (Issue #56)
154
+ * @returns Confidence result with manual review requirements
155
+ */
156
+ calculateConfidence(tool: Tool, isVulnerable: boolean, evidence: string, responseText: string, payload: SecurityPayload, sanitizationResult?: SanitizationDetectionResult): ConfidenceResult;
157
+ /**
158
+ * Check if tool is a structured data tool
159
+ */
160
+ isStructuredDataTool(toolName: string, toolDescription: string): boolean;
161
+ /**
162
+ * Check if response is returning search results
163
+ */
164
+ isSearchResultResponse(responseText: string): boolean;
165
+ /**
166
+ * Check if response is from a creation/modification operation
167
+ */
168
+ isCreationResponse(responseText: string): boolean;
169
+ /**
170
+ * Extract response content
171
+ */
172
+ extractResponseContent(response: CompatibilityCallToolResult): string;
173
+ /**
174
+ * Extract error info from response
175
+ */
176
+ private extractErrorInfo;
177
+ }
178
+ //# sourceMappingURL=SecurityResponseAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurityResponseAnalyzer.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/SecurityResponseAnalyzer.ts"],"names":[],"mappings":"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"}