@bryan-thompson/inspector-assessment-client 1.25.4 → 1.25.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{OAuthCallback-DE62cdTZ.js → OAuthCallback-D6y8tFfF.js} +1 -1
- package/dist/assets/{OAuthDebugCallback-CWjFdCIE.js → OAuthDebugCallback-DHegnqTa.js} +1 -1
- package/dist/assets/{index-PCQVSwHa.js → index-Cu02Ah3g.js} +4 -4
- package/dist/assets/{index-Df9Sx1jt.css → index-cHhcEXbr.css} +4 -0
- package/dist/index.html +2 -2
- package/lib/lib/assessment/coreTypes.d.ts +65 -0
- package/lib/lib/assessment/coreTypes.d.ts.map +1 -1
- package/lib/lib/assessment/extendedTypes.d.ts +127 -0
- package/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
- package/lib/lib/assessment/resultTypes.d.ts +45 -0
- package/lib/lib/assessment/resultTypes.d.ts.map +1 -1
- package/lib/lib/moduleScoring.d.ts +2 -2
- package/lib/lib/moduleScoring.d.ts.map +1 -1
- package/lib/lib/moduleScoring.js +3 -2
- package/lib/services/assessment/AssessmentOrchestrator.d.ts +3 -7
- package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
- package/lib/services/assessment/AssessmentOrchestrator.js +13 -2
- package/lib/services/assessment/TestDataGenerator.d.ts +9 -1
- package/lib/services/assessment/TestDataGenerator.d.ts.map +1 -1
- package/lib/services/assessment/TestDataGenerator.js +32 -6
- package/lib/services/assessment/TestScenarioEngine.d.ts +9 -1
- package/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -1
- package/lib/services/assessment/TestScenarioEngine.js +17 -14
- package/lib/services/assessment/config/annotationPatterns.d.ts +3 -1
- package/lib/services/assessment/config/annotationPatterns.d.ts.map +1 -1
- package/lib/services/assessment/config/annotationPatterns.js +5 -2
- package/lib/services/assessment/config/architecturePatterns.d.ts +101 -0
- package/lib/services/assessment/config/architecturePatterns.d.ts.map +1 -0
- package/lib/services/assessment/config/architecturePatterns.js +248 -0
- package/lib/services/assessment/config/performanceConfig.d.ts +122 -0
- package/lib/services/assessment/config/performanceConfig.d.ts.map +1 -0
- package/lib/services/assessment/config/performanceConfig.js +154 -0
- package/lib/services/assessment/config/sanitizationPatterns.d.ts +63 -0
- package/lib/services/assessment/config/sanitizationPatterns.d.ts.map +1 -0
- package/lib/services/assessment/config/sanitizationPatterns.js +223 -0
- package/lib/services/assessment/lib/claudeCodeBridge.d.ts +40 -3
- package/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -1
- package/lib/services/assessment/lib/claudeCodeBridge.js +149 -8
- package/lib/services/assessment/lib/concurrencyLimit.d.ts +6 -2
- package/lib/services/assessment/lib/concurrencyLimit.d.ts.map +1 -1
- package/lib/services/assessment/lib/concurrencyLimit.js +13 -6
- package/lib/services/assessment/lib/errors.d.ts +90 -0
- package/lib/services/assessment/lib/errors.d.ts.map +1 -0
- package/lib/services/assessment/lib/errors.js +136 -0
- package/lib/services/assessment/lib/timeoutUtils.d.ts +69 -0
- package/lib/services/assessment/lib/timeoutUtils.d.ts.map +1 -0
- package/lib/services/assessment/lib/timeoutUtils.js +103 -0
- package/lib/services/assessment/modules/BaseAssessor.d.ts +43 -8
- package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/BaseAssessor.js +103 -34
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts +38 -1
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.js +185 -19
- package/lib/services/assessment/modules/DocumentationAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/DocumentationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/DocumentationAssessor.js +11 -0
- package/lib/services/assessment/modules/ErrorHandlingAssessor.js +1 -1
- package/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/FunctionalityAssessor.js +6 -3
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts +3 -0
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +14 -2
- package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ManifestValidationAssessor.js +7 -2
- package/lib/services/assessment/modules/PromptAssessor.d.ts +1 -0
- package/lib/services/assessment/modules/PromptAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/PromptAssessor.js +26 -16
- package/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ProtocolComplianceAssessor.js +6 -2
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.js +15 -0
- package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ResourceAssessor.js +8 -2
- package/lib/services/assessment/modules/SecurityAssessor.d.ts +3 -171
- package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/SecurityAssessor.js +25 -1480
- package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +27 -28
- package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ToolAnnotationAssessor.js +340 -863
- package/lib/services/assessment/modules/UsabilityAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/UsabilityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/UsabilityAssessor.js +11 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts +57 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.js +176 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts +67 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.js +239 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts +46 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.js +394 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts +64 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.js +304 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts +43 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +276 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts +122 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.js +388 -0
- package/lib/services/assessment/modules/annotations/index.d.ts +13 -0
- package/lib/services/assessment/modules/annotations/index.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/index.js +15 -0
- package/lib/services/assessment/modules/index.d.ts +10 -0
- package/lib/services/assessment/modules/index.d.ts.map +1 -1
- package/lib/services/assessment/modules/index.js +13 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts +125 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.js +345 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts +33 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +128 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts +67 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +372 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +178 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +1207 -0
- package/lib/services/assessment/modules/securityTests/index.d.ts +8 -0
- package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/index.js +7 -0
- package/lib/services/assessment/tool-classifier-patterns.d.ts +1 -0
- package/lib/services/assessment/tool-classifier-patterns.d.ts.map +1 -1
- package/lib/services/assessment/tool-classifier-patterns.js +17 -0
- package/package.json +1 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitization Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects sanitization libraries and practices from tool metadata/descriptions.
|
|
5
|
+
* Used to reduce false positives when tools have proper input sanitization in place.
|
|
6
|
+
*
|
|
7
|
+
* @see Issue #56: Improve security analysis granularity
|
|
8
|
+
*/
|
|
9
|
+
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
10
|
+
import { SanitizationCategory } from "../../config/sanitizationPatterns.js";
|
|
11
|
+
/**
|
|
12
|
+
* Result of sanitization detection analysis
|
|
13
|
+
*/
|
|
14
|
+
export interface SanitizationDetectionResult {
|
|
15
|
+
/** Whether any sanitization was detected */
|
|
16
|
+
detected: boolean;
|
|
17
|
+
/** Specific libraries detected by name */
|
|
18
|
+
libraries: string[];
|
|
19
|
+
/** Categories of sanitization detected */
|
|
20
|
+
categories: SanitizationCategory[];
|
|
21
|
+
/** Generic sanitization keywords found */
|
|
22
|
+
genericPatterns: string[];
|
|
23
|
+
/** Total confidence adjustment (0-50 capped) */
|
|
24
|
+
totalConfidenceAdjustment: number;
|
|
25
|
+
/** Evidence strings for what was detected */
|
|
26
|
+
evidence: string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Result of input reflection analysis
|
|
30
|
+
*/
|
|
31
|
+
export interface ReflectionAnalysis {
|
|
32
|
+
/** Whether the input was reflected in the response */
|
|
33
|
+
reflected: boolean;
|
|
34
|
+
/** Type of reflection detected */
|
|
35
|
+
reflectionType: "exact" | "partial" | "transformed" | "none";
|
|
36
|
+
/** Specific parts that were matched (for partial reflection) */
|
|
37
|
+
partialMatches: string[];
|
|
38
|
+
/** Confidence reduction based on reflection analysis */
|
|
39
|
+
confidenceReduction: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Detects sanitization patterns in tool descriptions, metadata, and responses.
|
|
43
|
+
* Uses pattern matching to identify known security libraries and generic
|
|
44
|
+
* sanitization practices.
|
|
45
|
+
*/
|
|
46
|
+
export declare class SanitizationDetector {
|
|
47
|
+
/**
|
|
48
|
+
* Detect sanitization from tool description and metadata
|
|
49
|
+
*
|
|
50
|
+
* @param tool - MCP Tool object with name, description, and inputSchema
|
|
51
|
+
* @returns Detection result with libraries, categories, and confidence adjustment
|
|
52
|
+
*/
|
|
53
|
+
detect(tool: Tool): SanitizationDetectionResult;
|
|
54
|
+
/**
|
|
55
|
+
* Detect sanitization from arbitrary text (e.g., prompt descriptions)
|
|
56
|
+
*
|
|
57
|
+
* @param text - Text content to analyze
|
|
58
|
+
* @returns Detection result
|
|
59
|
+
*/
|
|
60
|
+
detectFromText(text: string): SanitizationDetectionResult;
|
|
61
|
+
/**
|
|
62
|
+
* Detect sanitization indicators in tool response content
|
|
63
|
+
*
|
|
64
|
+
* @param responseText - Response text from tool execution
|
|
65
|
+
* @returns Detection result focusing on response-time evidence
|
|
66
|
+
*/
|
|
67
|
+
detectInResponse(responseText: string): SanitizationDetectionResult;
|
|
68
|
+
/**
|
|
69
|
+
* Merge multiple detection results into one
|
|
70
|
+
*
|
|
71
|
+
* @param results - Array of detection results to merge
|
|
72
|
+
* @returns Combined result with deduplicated values
|
|
73
|
+
*/
|
|
74
|
+
mergeResults(...results: SanitizationDetectionResult[]): SanitizationDetectionResult;
|
|
75
|
+
/**
|
|
76
|
+
* Analyze whether input payload was reflected in the response
|
|
77
|
+
*
|
|
78
|
+
* @param payload - Original payload that was sent
|
|
79
|
+
* @param responseText - Response text to check for reflection
|
|
80
|
+
* @returns Reflection analysis with type and confidence reduction
|
|
81
|
+
*/
|
|
82
|
+
detectInputReflection(payload: string, responseText: string): ReflectionAnalysis;
|
|
83
|
+
/**
|
|
84
|
+
* Extract all analyzable text from a tool definition
|
|
85
|
+
*/
|
|
86
|
+
private extractToolText;
|
|
87
|
+
/**
|
|
88
|
+
* Recursively extract text from JSON schema
|
|
89
|
+
*/
|
|
90
|
+
private extractSchemaText;
|
|
91
|
+
/**
|
|
92
|
+
* Analyze text for sanitization patterns
|
|
93
|
+
*/
|
|
94
|
+
private analyzeText;
|
|
95
|
+
/**
|
|
96
|
+
* Check if text matches a library pattern
|
|
97
|
+
*/
|
|
98
|
+
private matchesLibrary;
|
|
99
|
+
/**
|
|
100
|
+
* Check if a generic keyword match is part of an already-detected library name
|
|
101
|
+
*/
|
|
102
|
+
private isPartOfLibraryMatch;
|
|
103
|
+
/**
|
|
104
|
+
* Calculate total confidence adjustment from detection results
|
|
105
|
+
*/
|
|
106
|
+
private calculateTotalAdjustment;
|
|
107
|
+
/**
|
|
108
|
+
* Extract key parts of a payload for partial matching
|
|
109
|
+
*
|
|
110
|
+
* Extracts significant portions that would indicate reflection:
|
|
111
|
+
* - Command keywords (SELECT, DROP, rm, etc.)
|
|
112
|
+
* - Injection markers (', ", --, etc.)
|
|
113
|
+
* - Common payload strings
|
|
114
|
+
*/
|
|
115
|
+
private extractKeyPayloadParts;
|
|
116
|
+
/**
|
|
117
|
+
* Check if payload appears in transformed form (encoded/escaped)
|
|
118
|
+
*/
|
|
119
|
+
private checkTransformedReflection;
|
|
120
|
+
/**
|
|
121
|
+
* Create an empty detection result
|
|
122
|
+
*/
|
|
123
|
+
private createEmptyResult;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=SanitizationDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SanitizationDetector.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/SanitizationDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC1D,OAAO,EAKL,oBAAoB,EAErB,MAAM,mCAAmC,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,4CAA4C;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,0CAA0C;IAC1C,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,0CAA0C;IAC1C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gDAAgD;IAChD,yBAAyB,EAAE,MAAM,CAAC;IAClC,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,kCAAkC;IAClC,cAAc,EAAE,OAAO,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC;IAC7D,gEAAgE;IAChE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,wDAAwD;IACxD,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,qBAAa,oBAAoB;IAC/B;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,2BAA2B;IAQ/C;;;;;OAKG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,2BAA2B;IAIzD;;;;;OAKG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,2BAA2B;IA4BnE;;;;;OAKG;IACH,YAAY,CACV,GAAG,OAAO,EAAE,2BAA2B,EAAE,GACxC,2BAA2B;IAwC9B;;;;;;OAMG;IACH,qBAAqB,CACnB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,kBAAkB;IAwDrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoCzB;;OAEG;IACH,OAAO,CAAC,WAAW;IAqCnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAOtB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAU5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAuBhC;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAqC9B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA4ClC;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAU1B"}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitization Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects sanitization libraries and practices from tool metadata/descriptions.
|
|
5
|
+
* Used to reduce false positives when tools have proper input sanitization in place.
|
|
6
|
+
*
|
|
7
|
+
* @see Issue #56: Improve security analysis granularity
|
|
8
|
+
*/
|
|
9
|
+
import { SANITIZATION_LIBRARY_PATTERNS, GENERIC_SANITIZATION_KEYWORDS, RESPONSE_SANITIZATION_INDICATORS, CONFIDENCE_BOOSTS, } from "../../config/sanitizationPatterns.js";
|
|
10
|
+
/**
|
|
11
|
+
* Detects sanitization patterns in tool descriptions, metadata, and responses.
|
|
12
|
+
* Uses pattern matching to identify known security libraries and generic
|
|
13
|
+
* sanitization practices.
|
|
14
|
+
*/
|
|
15
|
+
export class SanitizationDetector {
|
|
16
|
+
/**
|
|
17
|
+
* Detect sanitization from tool description and metadata
|
|
18
|
+
*
|
|
19
|
+
* @param tool - MCP Tool object with name, description, and inputSchema
|
|
20
|
+
* @returns Detection result with libraries, categories, and confidence adjustment
|
|
21
|
+
*/
|
|
22
|
+
detect(tool) {
|
|
23
|
+
// Gather all text to analyze from the tool
|
|
24
|
+
const textSources = this.extractToolText(tool);
|
|
25
|
+
const fullText = textSources.join(" ");
|
|
26
|
+
return this.analyzeText(fullText);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Detect sanitization from arbitrary text (e.g., prompt descriptions)
|
|
30
|
+
*
|
|
31
|
+
* @param text - Text content to analyze
|
|
32
|
+
* @returns Detection result
|
|
33
|
+
*/
|
|
34
|
+
detectFromText(text) {
|
|
35
|
+
return this.analyzeText(text);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Detect sanitization indicators in tool response content
|
|
39
|
+
*
|
|
40
|
+
* @param responseText - Response text from tool execution
|
|
41
|
+
* @returns Detection result focusing on response-time evidence
|
|
42
|
+
*/
|
|
43
|
+
detectInResponse(responseText) {
|
|
44
|
+
const result = this.createEmptyResult();
|
|
45
|
+
// Check for response-time sanitization indicators
|
|
46
|
+
for (const pattern of RESPONSE_SANITIZATION_INDICATORS) {
|
|
47
|
+
if (pattern.test(responseText)) {
|
|
48
|
+
result.detected = true;
|
|
49
|
+
const match = responseText.match(pattern);
|
|
50
|
+
if (match) {
|
|
51
|
+
result.genericPatterns.push(match[0]);
|
|
52
|
+
result.evidence.push(`Response contains sanitization indicator: "${match[0]}"`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Calculate adjustment for response evidence
|
|
57
|
+
if (result.genericPatterns.length > 0) {
|
|
58
|
+
result.totalConfidenceAdjustment = Math.min(result.genericPatterns.length * CONFIDENCE_BOOSTS.RESPONSE_EVIDENCE, CONFIDENCE_BOOSTS.MAX_ADJUSTMENT);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Merge multiple detection results into one
|
|
64
|
+
*
|
|
65
|
+
* @param results - Array of detection results to merge
|
|
66
|
+
* @returns Combined result with deduplicated values
|
|
67
|
+
*/
|
|
68
|
+
mergeResults(...results) {
|
|
69
|
+
const merged = this.createEmptyResult();
|
|
70
|
+
for (const result of results) {
|
|
71
|
+
if (result.detected) {
|
|
72
|
+
merged.detected = true;
|
|
73
|
+
}
|
|
74
|
+
// Deduplicate arrays
|
|
75
|
+
for (const lib of result.libraries) {
|
|
76
|
+
if (!merged.libraries.includes(lib)) {
|
|
77
|
+
merged.libraries.push(lib);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
for (const cat of result.categories) {
|
|
81
|
+
if (!merged.categories.includes(cat)) {
|
|
82
|
+
merged.categories.push(cat);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (const pattern of result.genericPatterns) {
|
|
86
|
+
if (!merged.genericPatterns.includes(pattern)) {
|
|
87
|
+
merged.genericPatterns.push(pattern);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const ev of result.evidence) {
|
|
91
|
+
if (!merged.evidence.includes(ev)) {
|
|
92
|
+
merged.evidence.push(ev);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Recalculate total adjustment
|
|
97
|
+
merged.totalConfidenceAdjustment = this.calculateTotalAdjustment(merged);
|
|
98
|
+
return merged;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Analyze whether input payload was reflected in the response
|
|
102
|
+
*
|
|
103
|
+
* @param payload - Original payload that was sent
|
|
104
|
+
* @param responseText - Response text to check for reflection
|
|
105
|
+
* @returns Reflection analysis with type and confidence reduction
|
|
106
|
+
*/
|
|
107
|
+
detectInputReflection(payload, responseText) {
|
|
108
|
+
const payloadLower = payload.toLowerCase();
|
|
109
|
+
const responseLower = responseText.toLowerCase();
|
|
110
|
+
// Check for exact match (case insensitive)
|
|
111
|
+
const exactMatch = responseLower.includes(payloadLower);
|
|
112
|
+
if (exactMatch) {
|
|
113
|
+
return {
|
|
114
|
+
reflected: true,
|
|
115
|
+
reflectionType: "exact",
|
|
116
|
+
partialMatches: [payload],
|
|
117
|
+
confidenceReduction: 0, // Exact reflection doesn't reduce confidence
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// Check for partial matches on key payload parts
|
|
121
|
+
const keyParts = this.extractKeyPayloadParts(payload);
|
|
122
|
+
const partialMatches = keyParts.filter((part) => responseLower.includes(part.toLowerCase()));
|
|
123
|
+
if (partialMatches.length > 0) {
|
|
124
|
+
return {
|
|
125
|
+
reflected: true,
|
|
126
|
+
reflectionType: "partial",
|
|
127
|
+
partialMatches,
|
|
128
|
+
confidenceReduction: 10, // Partial reflection has some reduction
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// Check for transformed reflection (encoded/escaped)
|
|
132
|
+
const transformedMatch = this.checkTransformedReflection(payload, responseText);
|
|
133
|
+
if (transformedMatch) {
|
|
134
|
+
return {
|
|
135
|
+
reflected: true,
|
|
136
|
+
reflectionType: "transformed",
|
|
137
|
+
partialMatches: [],
|
|
138
|
+
confidenceReduction: 15, // Transformed suggests sanitization applied
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
// No reflection detected - tool likely blocked/processed input safely
|
|
142
|
+
return {
|
|
143
|
+
reflected: false,
|
|
144
|
+
reflectionType: "none",
|
|
145
|
+
partialMatches: [],
|
|
146
|
+
confidenceReduction: 20, // No reflection = highest confidence reduction
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// ========== Private Helper Methods ==========
|
|
150
|
+
/**
|
|
151
|
+
* Extract all analyzable text from a tool definition
|
|
152
|
+
*/
|
|
153
|
+
extractToolText(tool) {
|
|
154
|
+
const texts = [];
|
|
155
|
+
// Tool name (less useful but might contain library names)
|
|
156
|
+
if (tool.name) {
|
|
157
|
+
texts.push(tool.name);
|
|
158
|
+
}
|
|
159
|
+
// Tool description (primary source)
|
|
160
|
+
if (tool.description) {
|
|
161
|
+
texts.push(tool.description);
|
|
162
|
+
}
|
|
163
|
+
// Input schema descriptions
|
|
164
|
+
if (tool.inputSchema) {
|
|
165
|
+
texts.push(...this.extractSchemaText(tool.inputSchema));
|
|
166
|
+
}
|
|
167
|
+
return texts;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Recursively extract text from JSON schema
|
|
171
|
+
*/
|
|
172
|
+
extractSchemaText(schema) {
|
|
173
|
+
const texts = [];
|
|
174
|
+
if (!schema || typeof schema !== "object") {
|
|
175
|
+
return texts;
|
|
176
|
+
}
|
|
177
|
+
const obj = schema;
|
|
178
|
+
// Extract description
|
|
179
|
+
if (typeof obj.description === "string") {
|
|
180
|
+
texts.push(obj.description);
|
|
181
|
+
}
|
|
182
|
+
// Extract title
|
|
183
|
+
if (typeof obj.title === "string") {
|
|
184
|
+
texts.push(obj.title);
|
|
185
|
+
}
|
|
186
|
+
// Recurse into properties
|
|
187
|
+
if (obj.properties && typeof obj.properties === "object") {
|
|
188
|
+
for (const prop of Object.values(obj.properties)) {
|
|
189
|
+
texts.push(...this.extractSchemaText(prop));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Recurse into items (for arrays)
|
|
193
|
+
if (obj.items) {
|
|
194
|
+
texts.push(...this.extractSchemaText(obj.items));
|
|
195
|
+
}
|
|
196
|
+
return texts;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Analyze text for sanitization patterns
|
|
200
|
+
*/
|
|
201
|
+
analyzeText(text) {
|
|
202
|
+
const result = this.createEmptyResult();
|
|
203
|
+
// Check for specific library patterns
|
|
204
|
+
for (const libPattern of SANITIZATION_LIBRARY_PATTERNS) {
|
|
205
|
+
if (this.matchesLibrary(text, libPattern)) {
|
|
206
|
+
result.detected = true;
|
|
207
|
+
result.libraries.push(libPattern.name);
|
|
208
|
+
if (!result.categories.includes(libPattern.category)) {
|
|
209
|
+
result.categories.push(libPattern.category);
|
|
210
|
+
}
|
|
211
|
+
result.evidence.push(`Library detected: ${libPattern.name}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Check for generic sanitization keywords (only if no specific library found)
|
|
215
|
+
// This prevents double-counting when a library name includes generic terms
|
|
216
|
+
for (const pattern of GENERIC_SANITIZATION_KEYWORDS) {
|
|
217
|
+
if (pattern.test(text)) {
|
|
218
|
+
const match = text.match(pattern);
|
|
219
|
+
if (match && !this.isPartOfLibraryMatch(match[0], result.libraries)) {
|
|
220
|
+
result.detected = true;
|
|
221
|
+
const keyword = match[0].toLowerCase();
|
|
222
|
+
if (!result.genericPatterns.includes(keyword)) {
|
|
223
|
+
result.genericPatterns.push(keyword);
|
|
224
|
+
result.evidence.push(`Sanitization keyword: "${keyword}"`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Calculate total adjustment
|
|
230
|
+
result.totalConfidenceAdjustment = this.calculateTotalAdjustment(result);
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Check if text matches a library pattern
|
|
235
|
+
*/
|
|
236
|
+
matchesLibrary(text, libPattern) {
|
|
237
|
+
return libPattern.patterns.some((pattern) => pattern.test(text));
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Check if a generic keyword match is part of an already-detected library name
|
|
241
|
+
*/
|
|
242
|
+
isPartOfLibraryMatch(keyword, detectedLibraries) {
|
|
243
|
+
const keywordLower = keyword.toLowerCase();
|
|
244
|
+
return detectedLibraries.some((lib) => lib.toLowerCase().includes(keywordLower));
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Calculate total confidence adjustment from detection results
|
|
248
|
+
*/
|
|
249
|
+
calculateTotalAdjustment(result) {
|
|
250
|
+
let adjustment = 0;
|
|
251
|
+
// Add library-specific boosts
|
|
252
|
+
for (const libName of result.libraries) {
|
|
253
|
+
const libPattern = SANITIZATION_LIBRARY_PATTERNS.find((p) => p.name === libName);
|
|
254
|
+
if (libPattern) {
|
|
255
|
+
adjustment += libPattern.confidenceBoost;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Add generic keyword boosts
|
|
259
|
+
adjustment +=
|
|
260
|
+
result.genericPatterns.length * CONFIDENCE_BOOSTS.GENERIC_KEYWORD;
|
|
261
|
+
// Cap at maximum
|
|
262
|
+
return Math.min(adjustment, CONFIDENCE_BOOSTS.MAX_ADJUSTMENT);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Extract key parts of a payload for partial matching
|
|
266
|
+
*
|
|
267
|
+
* Extracts significant portions that would indicate reflection:
|
|
268
|
+
* - Command keywords (SELECT, DROP, rm, etc.)
|
|
269
|
+
* - Injection markers (', ", --, etc.)
|
|
270
|
+
* - Common payload strings
|
|
271
|
+
*/
|
|
272
|
+
extractKeyPayloadParts(payload) {
|
|
273
|
+
const parts = [];
|
|
274
|
+
// SQL keywords
|
|
275
|
+
const sqlKeywords = payload.match(/\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|OR|AND)\b/gi);
|
|
276
|
+
if (sqlKeywords) {
|
|
277
|
+
parts.push(...sqlKeywords);
|
|
278
|
+
}
|
|
279
|
+
// Command injection keywords
|
|
280
|
+
const cmdKeywords = payload.match(/\b(rm|cat|ls|wget|curl|bash|sh|cmd|powershell)\b/gi);
|
|
281
|
+
if (cmdKeywords) {
|
|
282
|
+
parts.push(...cmdKeywords);
|
|
283
|
+
}
|
|
284
|
+
// Prompt injection markers
|
|
285
|
+
const promptMarkers = payload.match(/(ignore|previous|instructions|system|override|admin|root)/gi);
|
|
286
|
+
if (promptMarkers) {
|
|
287
|
+
parts.push(...promptMarkers);
|
|
288
|
+
}
|
|
289
|
+
// Path traversal patterns
|
|
290
|
+
const pathPatterns = payload.match(/\.\.\/|\.\.\\|\/etc\/|\/passwd/gi);
|
|
291
|
+
if (pathPatterns) {
|
|
292
|
+
parts.push(...pathPatterns);
|
|
293
|
+
}
|
|
294
|
+
// Deduplicate
|
|
295
|
+
return [...new Set(parts)];
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Check if payload appears in transformed form (encoded/escaped)
|
|
299
|
+
*/
|
|
300
|
+
checkTransformedReflection(payload, responseText) {
|
|
301
|
+
// Check for URL encoding
|
|
302
|
+
const urlEncoded = encodeURIComponent(payload);
|
|
303
|
+
if (responseText.includes(urlEncoded)) {
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
// Check for HTML entity encoding - basic (only < and >, most common)
|
|
307
|
+
const htmlBasicEscaped = payload
|
|
308
|
+
.replace(/</g, "<")
|
|
309
|
+
.replace(/>/g, ">");
|
|
310
|
+
if (responseText.includes(htmlBasicEscaped) &&
|
|
311
|
+
htmlBasicEscaped !== payload) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
// Check for HTML entity encoding - full (all special characters)
|
|
315
|
+
const htmlFullEscaped = payload
|
|
316
|
+
.replace(/&/g, "&")
|
|
317
|
+
.replace(/</g, "<")
|
|
318
|
+
.replace(/>/g, ">")
|
|
319
|
+
.replace(/"/g, """)
|
|
320
|
+
.replace(/'/g, "'");
|
|
321
|
+
if (responseText.includes(htmlFullEscaped) && htmlFullEscaped !== payload) {
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
// Check for backslash escaping
|
|
325
|
+
const backslashEscaped = payload.replace(/['"`]/g, "\\$&");
|
|
326
|
+
if (responseText.includes(backslashEscaped) &&
|
|
327
|
+
backslashEscaped !== payload) {
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Create an empty detection result
|
|
334
|
+
*/
|
|
335
|
+
createEmptyResult() {
|
|
336
|
+
return {
|
|
337
|
+
detected: false,
|
|
338
|
+
libraries: [],
|
|
339
|
+
categories: [],
|
|
340
|
+
genericPatterns: [],
|
|
341
|
+
totalConfidenceAdjustment: 0,
|
|
342
|
+
evidence: [],
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Payload Generator
|
|
3
|
+
* Creates test parameters for security payload injection
|
|
4
|
+
*
|
|
5
|
+
* Extracted from SecurityAssessor.ts for maintainability.
|
|
6
|
+
* Handles parameter creation, tool classification, and language-aware payloads.
|
|
7
|
+
*/
|
|
8
|
+
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
import { SecurityPayload } from "../../../../lib/securityPatterns.js";
|
|
10
|
+
/**
|
|
11
|
+
* Creates test parameters for security payload injection
|
|
12
|
+
*/
|
|
13
|
+
export declare class SecurityPayloadGenerator {
|
|
14
|
+
private languageGenerator;
|
|
15
|
+
/**
|
|
16
|
+
* Check if tool has input parameters
|
|
17
|
+
*/
|
|
18
|
+
hasInputParameters(tool: Tool): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Create test parameters using payload
|
|
21
|
+
*/
|
|
22
|
+
createTestParameters(payload: SecurityPayload, tool: Tool): Record<string, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* Check if tool is an API wrapper (safe data-passing tool)
|
|
25
|
+
*/
|
|
26
|
+
isApiWrapper(tool: Tool): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Check if attack is an execution-based test
|
|
29
|
+
* These tests assume the tool executes input as code
|
|
30
|
+
*/
|
|
31
|
+
isExecutionTest(attackName: string): boolean;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=SecurityPayloadGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecurityPayloadGenerator.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/SecurityPayloadGenerator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAIzD;;GAEG;AACH,qBAAa,wBAAwB;IACnC,OAAO,CAAC,iBAAiB,CAAuC;IAEhE;;OAEG;IACH,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAUvC;;OAEG;IACH,oBAAoB,CAClB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,IAAI,GACT,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAwG1B;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IASjC;;;OAGG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;CAQ7C"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Payload Generator
|
|
3
|
+
* Creates test parameters for security payload injection
|
|
4
|
+
*
|
|
5
|
+
* Extracted from SecurityAssessor.ts for maintainability.
|
|
6
|
+
* Handles parameter creation, tool classification, and language-aware payloads.
|
|
7
|
+
*/
|
|
8
|
+
import { ToolClassifier, ToolCategory } from "../../ToolClassifier.js";
|
|
9
|
+
import { LanguageAwarePayloadGenerator } from "../../LanguageAwarePayloadGenerator.js";
|
|
10
|
+
/**
|
|
11
|
+
* Creates test parameters for security payload injection
|
|
12
|
+
*/
|
|
13
|
+
export class SecurityPayloadGenerator {
|
|
14
|
+
languageGenerator = new LanguageAwarePayloadGenerator();
|
|
15
|
+
/**
|
|
16
|
+
* Check if tool has input parameters
|
|
17
|
+
*/
|
|
18
|
+
hasInputParameters(tool) {
|
|
19
|
+
const schema = tool.inputSchema?.type === "object" ? tool.inputSchema : tool.inputSchema;
|
|
20
|
+
return (schema?.properties !== undefined &&
|
|
21
|
+
Object.keys(schema.properties).length > 0);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create test parameters using payload
|
|
25
|
+
*/
|
|
26
|
+
createTestParameters(payload, tool) {
|
|
27
|
+
const schema = tool.inputSchema?.type === "object" ? tool.inputSchema : tool.inputSchema;
|
|
28
|
+
if (!schema?.properties) {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
const params = {};
|
|
32
|
+
const targetParamTypes = payload.parameterTypes || [];
|
|
33
|
+
let payloadInjected = false;
|
|
34
|
+
// Check for language-specific code execution parameters first
|
|
35
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
36
|
+
const propSchema = prop;
|
|
37
|
+
if (propSchema.type !== "string")
|
|
38
|
+
continue;
|
|
39
|
+
const detectedLanguage = this.languageGenerator.detectLanguage(key, tool.name, tool.description);
|
|
40
|
+
if (detectedLanguage !== "generic" && !payloadInjected) {
|
|
41
|
+
const languagePayloads = this.languageGenerator.getPayloadsForLanguage(detectedLanguage);
|
|
42
|
+
if (languagePayloads.length > 0) {
|
|
43
|
+
const payloadLower = payload.payload.toLowerCase();
|
|
44
|
+
const isCommandTest = payloadLower.includes("whoami") ||
|
|
45
|
+
payloadLower.includes("passwd") ||
|
|
46
|
+
payloadLower.includes("id");
|
|
47
|
+
let selectedPayload = languagePayloads[0];
|
|
48
|
+
if (isCommandTest) {
|
|
49
|
+
const cmdPayload = languagePayloads.find((lp) => lp.payload.includes("whoami") ||
|
|
50
|
+
lp.payload.includes("subprocess") ||
|
|
51
|
+
lp.payload.includes("execSync"));
|
|
52
|
+
if (cmdPayload)
|
|
53
|
+
selectedPayload = cmdPayload;
|
|
54
|
+
}
|
|
55
|
+
params[key] = selectedPayload.payload;
|
|
56
|
+
payloadInjected = true;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Fall back to parameterTypes matching
|
|
62
|
+
if (!payloadInjected && targetParamTypes.length > 0) {
|
|
63
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
64
|
+
const propSchema = prop;
|
|
65
|
+
const paramNameLower = key.toLowerCase();
|
|
66
|
+
if (propSchema.type === "string" &&
|
|
67
|
+
targetParamTypes.some((type) => paramNameLower.includes(type))) {
|
|
68
|
+
params[key] = payload.payload;
|
|
69
|
+
payloadInjected = true;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Fall back to generic payload - inject into first string parameter
|
|
75
|
+
if (!payloadInjected) {
|
|
76
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
77
|
+
const propSchema = prop;
|
|
78
|
+
if (propSchema.type === "string" && !payloadInjected) {
|
|
79
|
+
params[key] = payload.payload;
|
|
80
|
+
payloadInjected = true;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Fill required parameters with safe defaults
|
|
86
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
87
|
+
const propSchema = prop;
|
|
88
|
+
if (schema.required?.includes(key) && !(key in params)) {
|
|
89
|
+
if (propSchema.type === "string") {
|
|
90
|
+
params[key] = "test";
|
|
91
|
+
}
|
|
92
|
+
else if (propSchema.type === "number") {
|
|
93
|
+
params[key] = 1;
|
|
94
|
+
}
|
|
95
|
+
else if (propSchema.type === "boolean") {
|
|
96
|
+
params[key] = true;
|
|
97
|
+
}
|
|
98
|
+
else if (propSchema.type === "object") {
|
|
99
|
+
params[key] = {};
|
|
100
|
+
}
|
|
101
|
+
else if (propSchema.type === "array") {
|
|
102
|
+
params[key] = [];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return params;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if tool is an API wrapper (safe data-passing tool)
|
|
110
|
+
*/
|
|
111
|
+
isApiWrapper(tool) {
|
|
112
|
+
const classifier = new ToolClassifier();
|
|
113
|
+
const classification = classifier.classify(tool.name, tool.description || "");
|
|
114
|
+
return classification.categories.includes(ToolCategory.API_WRAPPER);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if attack is an execution-based test
|
|
118
|
+
* These tests assume the tool executes input as code
|
|
119
|
+
*/
|
|
120
|
+
isExecutionTest(attackName) {
|
|
121
|
+
const executionTests = [
|
|
122
|
+
"Command Injection",
|
|
123
|
+
"SQL Injection",
|
|
124
|
+
"Path Traversal",
|
|
125
|
+
];
|
|
126
|
+
return executionTests.includes(attackName);
|
|
127
|
+
}
|
|
128
|
+
}
|