@bryan-thompson/inspector-assessment-client 1.26.6 → 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.
- package/lib/lib/assessment/configTypes.d.ts +2 -0
- package/lib/lib/assessment/configTypes.d.ts.map +1 -1
- package/lib/lib/securityPatterns.d.ts +4 -2
- package/lib/lib/securityPatterns.d.ts.map +1 -1
- package/lib/lib/securityPatterns.js +146 -2
- package/lib/services/assessment/modules/AUPComplianceAssessor.js +9 -9
- package/lib/services/assessment/modules/AuthenticationAssessor.js +4 -4
- package/lib/services/assessment/modules/BaseAssessor.d.ts +0 -14
- package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/BaseAssessor.js +1 -33
- package/lib/services/assessment/modules/CrossCapabilitySecurityAssessor.js +1 -1
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.js +1 -1
- package/lib/services/assessment/modules/DocumentationAssessor.js +2 -2
- package/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ErrorHandlingAssessor.js +8 -8
- package/lib/services/assessment/modules/ExternalAPIScannerAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ExternalAPIScannerAssessor.js +3 -3
- package/lib/services/assessment/modules/FunctionalityAssessor.js +9 -9
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +12 -12
- package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ManifestValidationAssessor.js +9 -5
- package/lib/services/assessment/modules/PortabilityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/PortabilityAssessor.js +3 -3
- package/lib/services/assessment/modules/ProhibitedLibrariesAssessor.js +4 -4
- package/lib/services/assessment/modules/PromptAssessor.js +2 -2
- package/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ProtocolComplianceAssessor.js +7 -7
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.js +1 -1
- package/lib/services/assessment/modules/ResourceAssessor.js +1 -1
- package/lib/services/assessment/modules/SecurityAssessor.d.ts +25 -2
- package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/SecurityAssessor.js +149 -17
- package/lib/services/assessment/modules/TemporalAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/TemporalAssessor.js +10 -10
- package/lib/services/assessment/modules/ToolAnnotationAssessor.js +9 -9
- package/lib/services/assessment/modules/UsabilityAssessor.js +1 -1
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -1
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +37 -0
- package/lib/services/assessment/modules/index.d.ts +3 -0
- package/lib/services/assessment/modules/index.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/ChainExecutionTester.d.ts +104 -0
- package/lib/services/assessment/modules/securityTests/ChainExecutionTester.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/ChainExecutionTester.js +257 -0
- package/lib/services/assessment/modules/securityTests/CrossToolStateTester.d.ts +91 -0
- package/lib/services/assessment/modules/securityTests/CrossToolStateTester.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/CrossToolStateTester.js +225 -0
- package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts +120 -0
- package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.js +338 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +59 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +168 -0
- package/lib/services/assessment/modules/securityTests/index.d.ts +3 -1
- package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/index.js +2 -0
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Security Assessor Module
|
|
3
|
-
* Tests for backend API security vulnerabilities using
|
|
3
|
+
* Tests for backend API security vulnerabilities using 26 focused patterns
|
|
4
4
|
*
|
|
5
5
|
* BASIC MODE (5 patterns - enableDomainTesting=false):
|
|
6
6
|
* Command Injection, Calculator Injection, SQL Injection, Path Traversal, Unicode Bypass
|
|
7
7
|
*
|
|
8
|
-
* ADVANCED MODE (all
|
|
8
|
+
* ADVANCED MODE (all 26 patterns - enableDomainTesting=true):
|
|
9
9
|
* - Critical Injection (6): Command, Calculator, SQL, Path Traversal, XXE, NoSQL
|
|
10
10
|
* - Input Validation (3): Type Safety, Boundary Testing, Required Fields
|
|
11
11
|
* - Protocol Compliance (2): MCP Error Format, Timeout Handling
|
|
@@ -14,13 +14,22 @@
|
|
|
14
14
|
* - Encoding Bypass (1): Unicode Bypass
|
|
15
15
|
* - Resource Exhaustion (1): DoS/Resource Exhaustion
|
|
16
16
|
* - Deserialization (1): Insecure Deserialization
|
|
17
|
+
* - Auth Bypass (1): Fail-open authentication vulnerabilities (CVE-2025-52882)
|
|
18
|
+
* - Cross-Tool State Bypass (1): Privilege escalation via shared state (Issue #92)
|
|
19
|
+
* - Chained Exploitation (1): Multi-tool chain execution attacks (Issue #93)
|
|
20
|
+
*
|
|
21
|
+
* SEQUENCE TESTING (enableSequenceTesting - default true):
|
|
22
|
+
* Tests for cross-tool privilege escalation by calling tool sequences
|
|
23
|
+
* Tests for multi-tool chain exploitation attacks
|
|
17
24
|
*/
|
|
18
25
|
import { BaseAssessor } from "./BaseAssessor.js";
|
|
19
|
-
import { SecurityPayloadTester, SecurityPayloadGenerator, } from "./securityTests/index.js";
|
|
26
|
+
import { SecurityPayloadTester, SecurityPayloadGenerator, CrossToolStateTester, ChainExecutionTester, } from "./securityTests/index.js";
|
|
20
27
|
import { ToolClassifier, ToolCategory } from "../ToolClassifier.js";
|
|
21
28
|
export class SecurityAssessor extends BaseAssessor {
|
|
22
29
|
payloadTester;
|
|
23
30
|
payloadGenerator;
|
|
31
|
+
crossToolStateTester;
|
|
32
|
+
chainTester;
|
|
24
33
|
claudeBridge = null;
|
|
25
34
|
/**
|
|
26
35
|
* Set the ClaudeCodeBridge for semantic analysis of security test results
|
|
@@ -29,7 +38,7 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
29
38
|
setClaudeBridge(bridge) {
|
|
30
39
|
this.claudeBridge = bridge;
|
|
31
40
|
if (bridge) {
|
|
32
|
-
this.
|
|
41
|
+
this.logger.info(`ClaudeCodeBridge enabled for security semantic analysis (transport: ${bridge.getTransport()})`);
|
|
33
42
|
}
|
|
34
43
|
}
|
|
35
44
|
/**
|
|
@@ -58,7 +67,7 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
58
67
|
return await this.claudeBridge.analyzeSecurityResponse(context);
|
|
59
68
|
}
|
|
60
69
|
catch (error) {
|
|
61
|
-
this.
|
|
70
|
+
this.logger.error("Claude semantic analysis failed", { error });
|
|
62
71
|
return null;
|
|
63
72
|
}
|
|
64
73
|
}
|
|
@@ -75,11 +84,19 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
75
84
|
};
|
|
76
85
|
// Create logger adapter
|
|
77
86
|
const testLogger = {
|
|
78
|
-
log: (message) => this.
|
|
79
|
-
logError: (message, error) => this.
|
|
87
|
+
log: (message) => this.logger.info(message),
|
|
88
|
+
logError: (message, error) => this.logger.error(message, { error }),
|
|
80
89
|
};
|
|
81
90
|
// Initialize payload tester with config, logger, and timeout function
|
|
82
91
|
this.payloadTester = new SecurityPayloadTester(payloadConfig, testLogger, this.executeWithTimeout.bind(this));
|
|
92
|
+
// Initialize cross-tool state tester (Issue #92)
|
|
93
|
+
this.crossToolStateTester = new CrossToolStateTester({
|
|
94
|
+
timeout: config.securityTestTimeout,
|
|
95
|
+
});
|
|
96
|
+
// Initialize chain execution tester (Issue #93)
|
|
97
|
+
this.chainTester = new ChainExecutionTester({
|
|
98
|
+
verbose: false,
|
|
99
|
+
});
|
|
83
100
|
}
|
|
84
101
|
async assess(context) {
|
|
85
102
|
// Select tools for testing first
|
|
@@ -91,8 +108,8 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
91
108
|
const validTests = allTests.filter((t) => !t.connectionError);
|
|
92
109
|
// Log connection error warning
|
|
93
110
|
if (connectionErrors.length > 0) {
|
|
94
|
-
this.
|
|
95
|
-
this.
|
|
111
|
+
this.logger.info(`⚠️ WARNING: ${connectionErrors.length} test${connectionErrors.length !== 1 ? "s" : ""} failed due to connection/server errors`);
|
|
112
|
+
this.logger.info(`Connection errors: ${connectionErrors.map((e) => `${e.toolName}:${e.testName} (${e.errorType})`).join(", ")}`);
|
|
96
113
|
}
|
|
97
114
|
// Progressive enhancement: refine medium/low confidence detections with Claude semantic analysis
|
|
98
115
|
// HIGH confidence detections bypass Claude (cost efficient), only uncertain cases get API calls
|
|
@@ -102,7 +119,7 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
102
119
|
// Find tests that need semantic refinement (medium/low confidence vulnerabilities)
|
|
103
120
|
const testsToRefine = validTests.filter((t) => t.vulnerable && (t.confidence === "medium" || t.confidence === "low"));
|
|
104
121
|
if (testsToRefine.length > 0) {
|
|
105
|
-
this.
|
|
122
|
+
this.logger.info(`🧠 Running Claude semantic analysis on ${testsToRefine.length} medium/low confidence detection(s)...`);
|
|
106
123
|
let refinedCount = 0;
|
|
107
124
|
let falsePositivesRemoved = 0;
|
|
108
125
|
for (const test of testsToRefine) {
|
|
@@ -123,18 +140,18 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
123
140
|
// False positive - mark as not vulnerable
|
|
124
141
|
test.vulnerable = false;
|
|
125
142
|
falsePositivesRemoved++;
|
|
126
|
-
this.
|
|
143
|
+
this.logger.info(` ✅ ${test.toolName}:${test.testName} - marked safe (${refinement.reasoning.substring(0, 100)}...)`);
|
|
127
144
|
}
|
|
128
145
|
else {
|
|
129
146
|
// Confirmed or upgraded - update confidence
|
|
130
147
|
test.confidence = refinement.refinedConfidence;
|
|
131
148
|
if (refinement.refinedConfidence === "high") {
|
|
132
|
-
this.
|
|
149
|
+
this.logger.info(` ⚠️ ${test.toolName}:${test.testName} - confirmed vulnerable (${refinement.reasoning.substring(0, 100)}...)`);
|
|
133
150
|
}
|
|
134
151
|
}
|
|
135
152
|
}
|
|
136
153
|
}
|
|
137
|
-
this.
|
|
154
|
+
this.logger.info(`🧠 Semantic analysis complete: ${refinedCount} refined, ${falsePositivesRemoved} false positives removed`);
|
|
138
155
|
}
|
|
139
156
|
}
|
|
140
157
|
// Count vulnerabilities from VALID tests only
|
|
@@ -169,6 +186,34 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
169
186
|
// Additional security checks for new patterns (only on selected tools)
|
|
170
187
|
const additionalVulnerabilities = await this.performAdditionalSecurityChecks(toolsToTest);
|
|
171
188
|
vulnerabilities.push(...additionalVulnerabilities);
|
|
189
|
+
// Cross-tool sequence testing (Issue #92, Challenge #7)
|
|
190
|
+
// Tests for privilege escalation via shared mutable state
|
|
191
|
+
if (this.config.enableSequenceTesting !== false) {
|
|
192
|
+
const crossToolResults = await this.runCrossToolSequenceTests(toolsToTest, context.callTool, context.onProgress);
|
|
193
|
+
for (const [pairKey, result] of crossToolResults) {
|
|
194
|
+
if (result.vulnerable) {
|
|
195
|
+
highRiskCount++;
|
|
196
|
+
const vulnerability = `Cross-tool privilege escalation: ${pairKey}`;
|
|
197
|
+
if (!vulnerabilities.includes(vulnerability)) {
|
|
198
|
+
vulnerabilities.push(vulnerability);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Chain exploitation testing (Issue #93, Challenge #6)
|
|
204
|
+
// Tests for multi-tool chain exploitation attacks
|
|
205
|
+
if (this.config.enableSequenceTesting !== false) {
|
|
206
|
+
const chainResults = await this.runChainExploitationTests(toolsToTest, context.callTool, context.onProgress);
|
|
207
|
+
for (const [testKey, result] of chainResults) {
|
|
208
|
+
if (result.vulnerable) {
|
|
209
|
+
highRiskCount++;
|
|
210
|
+
const vulnerability = `Chain exploitation: ${testKey} (${result.reason})`;
|
|
211
|
+
if (!vulnerabilities.includes(vulnerability)) {
|
|
212
|
+
vulnerabilities.push(vulnerability);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
172
217
|
// Determine overall risk level
|
|
173
218
|
const overallRiskLevel = this.determineOverallRiskLevel(highRiskCount, mediumRiskCount, vulnerabilities.length);
|
|
174
219
|
// Determine status (pass validTests array to check confidence levels, not allTests)
|
|
@@ -197,19 +242,19 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
197
242
|
const selectedTools = tools.filter((tool) => selectedNames.has(tool.name));
|
|
198
243
|
// Empty array means user explicitly selected 0 tools
|
|
199
244
|
if (this.config.selectedToolsForTesting.length === 0) {
|
|
200
|
-
this.
|
|
245
|
+
this.logger.info(`User selected 0 tools for security testing - skipping tests`);
|
|
201
246
|
return [];
|
|
202
247
|
}
|
|
203
248
|
// If no tools matched the names (config out of sync), log warning but respect selection
|
|
204
249
|
if (selectedTools.length === 0) {
|
|
205
|
-
this.
|
|
250
|
+
this.logger.info(`Warning: No tools matched selection (${this.config.selectedToolsForTesting.join(", ")})`);
|
|
206
251
|
return [];
|
|
207
252
|
}
|
|
208
|
-
this.
|
|
253
|
+
this.logger.info(`Testing ${selectedTools.length} selected tools out of ${tools.length} for security`);
|
|
209
254
|
return selectedTools;
|
|
210
255
|
}
|
|
211
256
|
// Default: test all tools
|
|
212
|
-
this.
|
|
257
|
+
this.logger.info(`Testing all ${tools.length} tools for security`);
|
|
213
258
|
return tools;
|
|
214
259
|
}
|
|
215
260
|
/**
|
|
@@ -235,6 +280,93 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
235
280
|
}
|
|
236
281
|
return vulnerabilities;
|
|
237
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Run cross-tool sequence tests for privilege escalation (Issue #92, Challenge #7)
|
|
285
|
+
* Tests tool pairs: modifier enables admin mode, then admin action succeeds
|
|
286
|
+
*/
|
|
287
|
+
async runCrossToolSequenceTests(tools, callTool, onProgress) {
|
|
288
|
+
const pairs = this.crossToolStateTester.identifyCrossToolPairs(tools);
|
|
289
|
+
if (pairs.length === 0) {
|
|
290
|
+
this.logger.info(`No cross-tool pairs identified for sequence testing`);
|
|
291
|
+
return new Map();
|
|
292
|
+
}
|
|
293
|
+
this.logger.info(`Running cross-tool sequence tests on ${pairs.length} tool pair(s)...`);
|
|
294
|
+
const results = await this.crossToolStateTester.runAllSequenceTests(tools, callTool, onProgress);
|
|
295
|
+
// Log results
|
|
296
|
+
const summary = this.crossToolStateTester.summarizeResults(results);
|
|
297
|
+
if (summary.vulnerable > 0) {
|
|
298
|
+
this.logger.info(`⚠️ Cross-tool privilege escalation detected in ${summary.vulnerable} pair(s): ${summary.vulnerablePairs.join(", ")}`);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
this.logger.info(`✅ No cross-tool privilege escalation detected (${summary.safe} safe, ${summary.errors} errors)`);
|
|
302
|
+
}
|
|
303
|
+
return results;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Run chain exploitation tests (Issue #93, Challenge #6)
|
|
307
|
+
* Tests for multi-tool chain exploitation attacks including:
|
|
308
|
+
* - Arbitrary tool invocation without allowlist
|
|
309
|
+
* - Output injection via {{output}} template
|
|
310
|
+
* - Recursive chain execution (DoS potential)
|
|
311
|
+
* - State poisoning between chain steps
|
|
312
|
+
*/
|
|
313
|
+
async runChainExploitationTests(tools, callTool, onProgress) {
|
|
314
|
+
const chainTools = this.chainTester.identifyChainExecutorTools(tools);
|
|
315
|
+
const allResults = new Map();
|
|
316
|
+
if (chainTools.length === 0) {
|
|
317
|
+
this.logger.info(`No chain executor tools identified for chain testing`);
|
|
318
|
+
return allResults;
|
|
319
|
+
}
|
|
320
|
+
this.logger.info(`Running chain exploitation tests on ${chainTools.length} tool(s)...`);
|
|
321
|
+
for (const tool of chainTools) {
|
|
322
|
+
const toolResults = await this.chainTester.runChainExploitationTests(callTool, tool);
|
|
323
|
+
// Aggregate results with tool name prefix and emit progress events
|
|
324
|
+
for (const [testName, result] of toolResults) {
|
|
325
|
+
allResults.set(`${tool.name}:${testName}`, result);
|
|
326
|
+
// Emit vulnerability_found progress event for vulnerable results
|
|
327
|
+
if (result.vulnerable && onProgress) {
|
|
328
|
+
const evidenceText = result.evidence
|
|
329
|
+
? `Chain payload: ${result.evidence.chainPayload}`
|
|
330
|
+
: `Chain exploitation detected: ${result.reason}`;
|
|
331
|
+
const vulnEvent = {
|
|
332
|
+
type: "vulnerability_found",
|
|
333
|
+
tool: tool.name,
|
|
334
|
+
pattern: `chain_exploitation:${testName}`,
|
|
335
|
+
confidence: "high",
|
|
336
|
+
evidence: evidenceText,
|
|
337
|
+
riskLevel: "HIGH",
|
|
338
|
+
requiresReview: true,
|
|
339
|
+
payload: result.evidence?.chainPayload,
|
|
340
|
+
};
|
|
341
|
+
onProgress(vulnEvent);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
// Log individual tool results
|
|
345
|
+
const summary = this.chainTester.summarizeResults(toolResults);
|
|
346
|
+
if (summary.vulnerable > 0) {
|
|
347
|
+
this.logger.info(`⚠️ Chain exploitation detected in ${tool.name}: ${summary.vulnerableTests.join(", ")}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Log overall summary
|
|
351
|
+
let totalVulnerable = 0;
|
|
352
|
+
let totalSafe = 0;
|
|
353
|
+
let totalErrors = 0;
|
|
354
|
+
for (const result of allResults.values()) {
|
|
355
|
+
if (result.reason === "test_error")
|
|
356
|
+
totalErrors++;
|
|
357
|
+
else if (result.vulnerable)
|
|
358
|
+
totalVulnerable++;
|
|
359
|
+
else
|
|
360
|
+
totalSafe++;
|
|
361
|
+
}
|
|
362
|
+
if (totalVulnerable > 0) {
|
|
363
|
+
this.logger.info(`⚠️ Chain exploitation total: ${totalVulnerable} vulnerable, ${totalSafe} safe, ${totalErrors} errors`);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
this.logger.info(`✅ No chain exploitation detected (${totalSafe} safe, ${totalErrors} errors)`);
|
|
367
|
+
}
|
|
368
|
+
return allResults;
|
|
369
|
+
}
|
|
238
370
|
/**
|
|
239
371
|
* Determine overall risk level
|
|
240
372
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TemporalAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/TemporalAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,uBAAuB,EAEvB,kBAAkB,EAGnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA+B9C,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,kBAAkB,CAAS;IAGnC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAoBnC;IAGF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAU;IAEjD;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAqBrC;IAEF;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAYzC;gBAEU,MAAM,EAAE,uBAAuB;IAKrC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAqEvD,UAAU;IAuHxB;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAkChC,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"TemporalAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/TemporalAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,uBAAuB,EAEvB,kBAAkB,EAGnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA+B9C,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,kBAAkB,CAAS;IAGnC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAoBnC;IAGF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAU;IAEjD;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAqBrC;IAEF;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAYzC;gBAEU,MAAM,EAAE,uBAAuB;IAKrC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAqEvD,UAAU;IAuHxB;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAkChC,OAAO,CAAC,gBAAgB;IAwJxB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAsC3B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAiFzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAetB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAmExB;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAgEjC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA2DxB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAuBtB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAiCzB;;;;;;;;OAQG;IACH,OAAO,CAAC,2BAA2B;IAmDnC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,mBAAmB;IA+C3B,OAAO,CAAC,uBAAuB;CA+DhC"}
|
|
@@ -110,10 +110,10 @@ export class TemporalAssessor extends BaseAssessor {
|
|
|
110
110
|
// Check if definition tracking is available
|
|
111
111
|
const canTrackDefinitions = typeof context.listTools === "function";
|
|
112
112
|
if (canTrackDefinitions) {
|
|
113
|
-
this.
|
|
113
|
+
this.logger.info(`Starting temporal assessment with ${this.invocationsPerTool} invocations per tool (definition tracking enabled)`);
|
|
114
114
|
}
|
|
115
115
|
else {
|
|
116
|
-
this.
|
|
116
|
+
this.logger.info(`Starting temporal assessment with ${this.invocationsPerTool} invocations per tool (definition tracking unavailable)`);
|
|
117
117
|
}
|
|
118
118
|
for (const tool of context.tools) {
|
|
119
119
|
// Skip if tool selection is configured and this tool isn't selected
|
|
@@ -125,11 +125,11 @@ export class TemporalAssessor extends BaseAssessor {
|
|
|
125
125
|
results.push(result);
|
|
126
126
|
if (result.vulnerable) {
|
|
127
127
|
rugPullsDetected++;
|
|
128
|
-
this.
|
|
128
|
+
this.logger.info(`RUG PULL DETECTED: ${tool.name} changed behavior at invocation ${result.firstDeviationAt}`);
|
|
129
129
|
}
|
|
130
130
|
if (result.definitionMutated) {
|
|
131
131
|
definitionMutationsDetected++;
|
|
132
|
-
this.
|
|
132
|
+
this.logger.info(`DEFINITION MUTATION DETECTED: ${tool.name} changed description at invocation ${result.definitionMutationAt}`);
|
|
133
133
|
}
|
|
134
134
|
// Respect delay between tests
|
|
135
135
|
if (this.config.delayBetweenTests) {
|
|
@@ -161,7 +161,7 @@ export class TemporalAssessor extends BaseAssessor {
|
|
|
161
161
|
: this.invocationsPerTool;
|
|
162
162
|
// Check if definition tracking is available
|
|
163
163
|
const canTrackDefinitions = typeof context.listTools === "function";
|
|
164
|
-
this.
|
|
164
|
+
this.logger.info(`Testing ${tool.name} with ${invocations} invocations${isDestructive ? " (reduced - destructive)" : ""}`);
|
|
165
165
|
for (let i = 1; i <= invocations; i++) {
|
|
166
166
|
this.testCount++;
|
|
167
167
|
// Track tool definition BEFORE each invocation (if available)
|
|
@@ -181,7 +181,7 @@ export class TemporalAssessor extends BaseAssessor {
|
|
|
181
181
|
}
|
|
182
182
|
catch {
|
|
183
183
|
// Definition tracking failed - continue with response tracking
|
|
184
|
-
this.
|
|
184
|
+
this.logger.info(`Warning: Failed to fetch tool definition for ${tool.name} at invocation ${i}`);
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
try {
|
|
@@ -296,10 +296,10 @@ export class TemporalAssessor extends BaseAssessor {
|
|
|
296
296
|
const isStateful = this.isStatefulTool(tool);
|
|
297
297
|
const isResourceCreating = this.isResourceCreatingTool(tool);
|
|
298
298
|
if (isStateful) {
|
|
299
|
-
this.
|
|
299
|
+
this.logger.info(`${tool.name} classified as stateful - using schema comparison`);
|
|
300
300
|
}
|
|
301
301
|
else if (isResourceCreating) {
|
|
302
|
-
this.
|
|
302
|
+
this.logger.info(`${tool.name} classified as resource-creating - using variance classification`);
|
|
303
303
|
}
|
|
304
304
|
for (let i = 1; i < responses.length; i++) {
|
|
305
305
|
if (responses[i].error) {
|
|
@@ -316,7 +316,7 @@ export class TemporalAssessor extends BaseAssessor {
|
|
|
316
316
|
const contentChange = this.detectStatefulContentChange(responses[0].response, responses[i].response);
|
|
317
317
|
if (contentChange.detected) {
|
|
318
318
|
isDifferent = true;
|
|
319
|
-
this.
|
|
319
|
+
this.logger.info(`${tool.name}: Content semantic change detected at invocation ${i + 1} - ${contentChange.reason}`);
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
if (isDifferent) {
|
|
@@ -335,7 +335,7 @@ export class TemporalAssessor extends BaseAssessor {
|
|
|
335
335
|
// LEGITIMATE variance is expected for resource-creating tools
|
|
336
336
|
if (classification.type !== "LEGITIMATE") {
|
|
337
337
|
deviations.push(i + 1);
|
|
338
|
-
this.
|
|
338
|
+
this.logger.info(`${tool.name}: ${classification.type} variance at invocation ${i + 1} - ${classification.reasons.join(", ")}`);
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
341
|
else {
|
|
@@ -39,14 +39,14 @@ export class ToolAnnotationAssessor extends BaseAssessor {
|
|
|
39
39
|
*/
|
|
40
40
|
setPatterns(patterns) {
|
|
41
41
|
this.compiledPatterns = patterns;
|
|
42
|
-
this.
|
|
42
|
+
this.logger.info("Custom annotation patterns configured");
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* Set Claude Code Bridge for enhanced behavior inference
|
|
46
46
|
*/
|
|
47
47
|
setClaudeBridge(bridge) {
|
|
48
48
|
this.claudeBridge = bridge;
|
|
49
|
-
this.
|
|
49
|
+
this.logger.info("Claude Code Bridge enabled for behavior inference");
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
* Check if Claude enhancement is available
|
|
@@ -59,7 +59,7 @@ export class ToolAnnotationAssessor extends BaseAssessor {
|
|
|
59
59
|
* Run tool annotation assessment
|
|
60
60
|
*/
|
|
61
61
|
async assess(context) {
|
|
62
|
-
this.
|
|
62
|
+
this.logger.info("Starting tool annotation assessment");
|
|
63
63
|
this.testCount = 0;
|
|
64
64
|
const toolResults = [];
|
|
65
65
|
let annotatedCount = 0;
|
|
@@ -82,7 +82,7 @@ export class ToolAnnotationAssessor extends BaseAssessor {
|
|
|
82
82
|
// Detect server persistence model from tool names
|
|
83
83
|
const toolNames = context.tools.map((t) => t.name);
|
|
84
84
|
this.persistenceContext = detectPersistenceModel(toolNames);
|
|
85
|
-
this.
|
|
85
|
+
this.logger.info(`Persistence model detected: ${this.persistenceContext.model} (confidence: ${this.persistenceContext.confidence})`);
|
|
86
86
|
// Issue #57: Detect server architecture
|
|
87
87
|
const architectureContext = {
|
|
88
88
|
tools: context.tools.map((t) => ({
|
|
@@ -97,7 +97,7 @@ export class ToolAnnotationAssessor extends BaseAssessor {
|
|
|
97
97
|
: undefined,
|
|
98
98
|
};
|
|
99
99
|
const architectureAnalysis = detectArchitecture(architectureContext);
|
|
100
|
-
this.
|
|
100
|
+
this.logger.info(`Architecture detected: ${architectureAnalysis.serverType} server, databases: ${architectureAnalysis.databaseBackends.join(", ") || "none"}, network: ${architectureAnalysis.requiresNetworkAccess}`);
|
|
101
101
|
// Issue #57: Behavior inference metrics tracking
|
|
102
102
|
const behaviorInferenceMetrics = {
|
|
103
103
|
namePatternMatches: 0,
|
|
@@ -108,7 +108,7 @@ export class ToolAnnotationAssessor extends BaseAssessor {
|
|
|
108
108
|
};
|
|
109
109
|
const useClaudeInference = this.isClaudeEnabled();
|
|
110
110
|
if (useClaudeInference) {
|
|
111
|
-
this.
|
|
111
|
+
this.logger.info("Claude Code integration enabled - using semantic behavior inference");
|
|
112
112
|
}
|
|
113
113
|
for (const tool of context.tools) {
|
|
114
114
|
this.testCount++;
|
|
@@ -211,7 +211,7 @@ export class ToolAnnotationAssessor extends BaseAssessor {
|
|
|
211
211
|
// Emit poisoned description event
|
|
212
212
|
if (latestResult.descriptionPoisoning?.detected) {
|
|
213
213
|
poisonedDescriptionsCount++;
|
|
214
|
-
this.
|
|
214
|
+
this.logger.info(`POISONED DESCRIPTION DETECTED: ${tool.name} contains suspicious patterns`);
|
|
215
215
|
if (context.onProgress) {
|
|
216
216
|
context.onProgress({
|
|
217
217
|
type: "annotation_poisoned",
|
|
@@ -229,7 +229,7 @@ export class ToolAnnotationAssessor extends BaseAssessor {
|
|
|
229
229
|
const explanation = this.generateExplanation(annotatedCount, missingAnnotationsCount, misalignedAnnotationsCount, context.tools.length);
|
|
230
230
|
const recommendations = this.generateRecommendations(toolResults);
|
|
231
231
|
const { metrics, alignmentBreakdown } = this.calculateMetrics(toolResults, context.tools.length);
|
|
232
|
-
this.
|
|
232
|
+
this.logger.info(`Assessment complete: ${annotatedCount}/${context.tools.length} tools annotated, ${misalignedAnnotationsCount} misaligned, ${alignmentBreakdown.reviewRecommended} need review, ${poisonedDescriptionsCount} poisoned`);
|
|
233
233
|
if (useClaudeInference) {
|
|
234
234
|
const highConfidenceMisalignments = toolResults.filter((r) => r.claudeInference &&
|
|
235
235
|
r.claudeInference.confidence >= 70 &&
|
|
@@ -467,7 +467,7 @@ export class ToolAnnotationAssessor extends BaseAssessor {
|
|
|
467
467
|
};
|
|
468
468
|
}
|
|
469
469
|
catch (error) {
|
|
470
|
-
this.
|
|
470
|
+
this.logger.error(`Claude inference failed for ${tool.name}`, { error });
|
|
471
471
|
return {
|
|
472
472
|
...baseResult,
|
|
473
473
|
claudeInference: {
|
|
@@ -16,7 +16,7 @@ export class UsabilityAssessor extends BaseAssessor {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
async assess(context) {
|
|
19
|
-
this.
|
|
19
|
+
this.logger.info("Starting usability assessment");
|
|
20
20
|
const metrics = this.analyzeUsability(context.tools);
|
|
21
21
|
const status = this.determineUsabilityStatus(metrics);
|
|
22
22
|
const explanation = this.generateExplanation(metrics, context.tools);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DescriptionPoisoningDetector.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/annotations/DescriptionPoisoningDetector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;QACpC,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC/C;AAED;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"DescriptionPoisoningDetector.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/annotations/DescriptionPoisoningDetector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;QACpC,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC/C;AAED;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,EAAE,gBAAgB,EAiR5D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,IAAI,GAAG,mBAAmB,CA+C3E"}
|
|
@@ -231,6 +231,43 @@ export const DESCRIPTION_POISONING_PATTERNS = [
|
|
|
231
231
|
severity: "HIGH",
|
|
232
232
|
category: "hidden_trigger",
|
|
233
233
|
},
|
|
234
|
+
// Cross-tool state dependency patterns (Issue #92, Challenge #7)
|
|
235
|
+
{
|
|
236
|
+
name: "shared_state_reference",
|
|
237
|
+
pattern: /\b(config_state|shared_state|global_state|runtime_config)\b/gi,
|
|
238
|
+
severity: "HIGH",
|
|
239
|
+
category: "state_dependency",
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: "cross_tool_dependency",
|
|
243
|
+
pattern: /set\s+by\s+(another|other|different)\s+tool/gi,
|
|
244
|
+
severity: "HIGH",
|
|
245
|
+
category: "state_dependency",
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: "admin_mode_check",
|
|
249
|
+
pattern: /\bchecks?\s+(admin[_-]?mode|privileged[_-]?mode)/gi,
|
|
250
|
+
severity: "HIGH",
|
|
251
|
+
category: "state_dependency",
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
name: "requires_prior_call",
|
|
255
|
+
pattern: /requires?\s+.*\s+(first|before|prior)/gi,
|
|
256
|
+
severity: "MEDIUM",
|
|
257
|
+
category: "state_dependency",
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "depends_on_tool",
|
|
261
|
+
pattern: /depends?\s+on\s+(tool|function|calling)/gi,
|
|
262
|
+
severity: "MEDIUM",
|
|
263
|
+
category: "state_dependency",
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "enable_admin_hint",
|
|
267
|
+
pattern: /enable\s+admin[_-]?mode|activate\s+admin/gi,
|
|
268
|
+
severity: "HIGH",
|
|
269
|
+
category: "state_dependency",
|
|
270
|
+
},
|
|
234
271
|
];
|
|
235
272
|
/**
|
|
236
273
|
* Scan tool description for poisoning patterns
|
|
@@ -90,4 +90,7 @@ export { MCPSpecComplianceAssessor } from "./MCPSpecComplianceAssessor.js";
|
|
|
90
90
|
* This export will be removed in v2.0.0.
|
|
91
91
|
*/
|
|
92
92
|
export { ProtocolConformanceAssessor } from "./ProtocolConformanceAssessor.js";
|
|
93
|
+
export type { MCPDirectoryAssessment, SecurityAssessment, FunctionalityAssessment, ErrorHandlingAssessment, DocumentationAssessment, UsabilityAssessment, MCPSpecComplianceAssessment, AssessmentStatus, } from "../../../lib/assessment/index.js";
|
|
94
|
+
export type { AssessmentConfiguration, } from "../../../lib/assessment/configTypes.js";
|
|
95
|
+
export type { ProgressCallback, ProgressEvent, } from "../../../lib/assessment/progressTypes.js";
|
|
93
96
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAMlE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAMpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAM1E;;;GAGG;AACH,cAAc,iBAAiB,CAAC;AAEhC;;;GAGG;AACH,cAAc,eAAe,CAAC;AAM9B;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;;;GAIG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;GAIG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE;;;;GAIG;AACH,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAMlE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAMpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAM1E;;;GAGG;AACH,cAAc,iBAAiB,CAAC;AAEhC;;;GAGG;AACH,cAAc,eAAe,CAAC;AAM9B;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;;;GAIG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;GAIG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE;;;;GAIG;AACH,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAM5E,YAAY,EAEV,sBAAsB,EACtB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,2BAA2B,EAE3B,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAEV,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EAEV,gBAAgB,EAChB,aAAa,GACd,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chain Execution Tester
|
|
3
|
+
* Dynamic testing for multi-tool chain exploitation vulnerabilities
|
|
4
|
+
*
|
|
5
|
+
* Issue #93, Challenge #6: Multi-tool chained exploitation attacks
|
|
6
|
+
* Tests for:
|
|
7
|
+
* 1. Arbitrary tool invocation without allowlist
|
|
8
|
+
* 2. Output injection via {{output}} template substitution
|
|
9
|
+
* 3. Recursive chain execution (DoS potential)
|
|
10
|
+
* 4. State poisoning between chain steps
|
|
11
|
+
* 5. Missing depth/size limits
|
|
12
|
+
*
|
|
13
|
+
* A/B Validation:
|
|
14
|
+
* - vulnerable-mcp (10900): Should detect all vulnerability categories
|
|
15
|
+
* - hardened-mcp (10901): 0 false positives (validation-only behavior)
|
|
16
|
+
*/
|
|
17
|
+
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
18
|
+
import { ChainExploitationAnalysis, ChainVulnerabilityCategory } from "./SecurityResponseAnalyzer.js";
|
|
19
|
+
import { CallToolFunction } from "./CrossToolStateTester.js";
|
|
20
|
+
export type { CallToolFunction } from "./CrossToolStateTester.js";
|
|
21
|
+
/**
|
|
22
|
+
* Reason for chain exploitation test result
|
|
23
|
+
*/
|
|
24
|
+
export type ChainTestReason = "chain_execution_confirmed" | "output_injection_detected" | "recursive_execution_detected" | "arbitrary_tool_accepted" | "state_poisoning_detected" | "validation_only" | "chain_rejected" | "tool_not_chain_executor" | "test_error";
|
|
25
|
+
/**
|
|
26
|
+
* Result of a single chain exploitation test
|
|
27
|
+
*/
|
|
28
|
+
export interface ChainExecutionTestResult {
|
|
29
|
+
vulnerable: boolean;
|
|
30
|
+
reason: ChainTestReason;
|
|
31
|
+
vulnerabilityCategories?: ChainVulnerabilityCategory[];
|
|
32
|
+
evidence?: {
|
|
33
|
+
chainPayload: string;
|
|
34
|
+
response: string;
|
|
35
|
+
analysisResult: ChainExploitationAnalysis;
|
|
36
|
+
};
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Summary of chain exploitation tests for a tool
|
|
41
|
+
*/
|
|
42
|
+
export interface ChainExploitationSummary {
|
|
43
|
+
total: number;
|
|
44
|
+
vulnerable: number;
|
|
45
|
+
safe: number;
|
|
46
|
+
errors: number;
|
|
47
|
+
vulnerableTests: string[];
|
|
48
|
+
vulnerabilityCategories: ChainVulnerabilityCategory[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Configuration for chain execution testing
|
|
52
|
+
*/
|
|
53
|
+
export interface ChainExecutionTesterConfig {
|
|
54
|
+
/** Enable verbose logging */
|
|
55
|
+
verbose?: boolean;
|
|
56
|
+
/** Maximum chain depth to test (default: 10) */
|
|
57
|
+
maxChainDepth?: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Tests for multi-tool chain exploitation vulnerabilities
|
|
61
|
+
*/
|
|
62
|
+
export declare class ChainExecutionTester {
|
|
63
|
+
private readonly verbose;
|
|
64
|
+
private analyzer;
|
|
65
|
+
constructor(config?: ChainExecutionTesterConfig);
|
|
66
|
+
/**
|
|
67
|
+
* Log message if verbose logging is enabled
|
|
68
|
+
*/
|
|
69
|
+
private log;
|
|
70
|
+
/**
|
|
71
|
+
* Identify tools that might be chain executors
|
|
72
|
+
* Looks for tools with names/descriptions/parameters suggesting chain execution
|
|
73
|
+
*/
|
|
74
|
+
identifyChainExecutorTools(tools: Tool[]): Tool[];
|
|
75
|
+
/**
|
|
76
|
+
* Get the parameter name for chain input from tool schema
|
|
77
|
+
*/
|
|
78
|
+
private getChainParamName;
|
|
79
|
+
/**
|
|
80
|
+
* Extract text content from tool response
|
|
81
|
+
*/
|
|
82
|
+
private extractResponseText;
|
|
83
|
+
/**
|
|
84
|
+
* Determine the vulnerability reason from analysis result
|
|
85
|
+
*/
|
|
86
|
+
private determineVulnerabilityReason;
|
|
87
|
+
/**
|
|
88
|
+
* Test single chain payload against a tool
|
|
89
|
+
*/
|
|
90
|
+
testChainPayload(callTool: CallToolFunction, tool: Tool, chainPayload: string, paramName?: string): Promise<ChainExecutionTestResult>;
|
|
91
|
+
/**
|
|
92
|
+
* Get test payloads for chain exploitation testing
|
|
93
|
+
*/
|
|
94
|
+
private getTestPayloads;
|
|
95
|
+
/**
|
|
96
|
+
* Run comprehensive chain exploitation tests on a tool
|
|
97
|
+
*/
|
|
98
|
+
runChainExploitationTests(callTool: CallToolFunction, tool: Tool): Promise<Map<string, ChainExecutionTestResult>>;
|
|
99
|
+
/**
|
|
100
|
+
* Summarize chain exploitation test results
|
|
101
|
+
*/
|
|
102
|
+
summarizeResults(results: Map<string, ChainExecutionTestResult>): ChainExploitationSummary;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=ChainExecutionTester.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChainExecutionTester.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/ChainExecutionTester.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAEL,IAAI,EACL,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAEL,yBAAyB,EACzB,0BAA0B,EAC3B,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,2BAA2B,GAC3B,2BAA2B,GAC3B,8BAA8B,GAC9B,yBAAyB,GACzB,0BAA0B,GAC1B,iBAAiB,GACjB,gBAAgB,GAChB,yBAAyB,GACzB,YAAY,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,eAAe,CAAC;IACxB,uBAAuB,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACvD,QAAQ,CAAC,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,yBAAyB,CAAC;KAC3C,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,uBAAuB,EAAE,0BAA0B,EAAE,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAWD;;GAEG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAA2B;gBAE/B,MAAM,GAAE,0BAA+B;IAKnD;;OAEG;IACH,OAAO,CAAC,GAAG;IAOX;;;OAGG;IACH,0BAA0B,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE;IA2CjD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAYzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkB3B;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAoBpC;;OAEG;IACG,gBAAgB,CACpB,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,wBAAwB,CAAC;IAkDpC;;OAEG;IACH,OAAO,CAAC,eAAe;IA2CvB;;OAEG;IACG,yBAAyB,CAC7B,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IA+BjD;;OAEG;IACH,gBAAgB,CACd,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,wBAAwB,CAAC,GAC7C,wBAAwB;CA4B5B"}
|