@bryan-thompson/inspector-assessment-client 1.25.1 → 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 (132) hide show
  1. package/dist/assets/{OAuthCallback-CkzX_H4T.js → OAuthCallback-Dl4GYls3.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-jZEkm74B.js → OAuthDebugCallback-BdJ38Z-r.js} +1 -1
  3. package/dist/assets/{index-Df9Sx1jt.css → index-cHhcEXbr.css} +4 -0
  4. package/dist/assets/{index-BVx1dGJT.js → index-pfUiTdQb.js} +4 -4
  5. package/dist/index.html +2 -2
  6. package/lib/lib/assessment/configTypes.d.ts +3 -0
  7. package/lib/lib/assessment/configTypes.d.ts.map +1 -1
  8. package/lib/lib/assessment/configTypes.js +11 -6
  9. package/lib/lib/assessment/coreTypes.d.ts +65 -0
  10. package/lib/lib/assessment/coreTypes.d.ts.map +1 -1
  11. package/lib/lib/assessment/extendedTypes.d.ts +127 -0
  12. package/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
  13. package/lib/lib/assessment/resultTypes.d.ts +45 -0
  14. package/lib/lib/assessment/resultTypes.d.ts.map +1 -1
  15. package/lib/services/assessment/AssessmentOrchestrator.d.ts +4 -12
  16. package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
  17. package/lib/services/assessment/AssessmentOrchestrator.js +49 -238
  18. package/lib/services/assessment/TestDataGenerator.d.ts +9 -1
  19. package/lib/services/assessment/TestDataGenerator.d.ts.map +1 -1
  20. package/lib/services/assessment/TestDataGenerator.js +32 -6
  21. package/lib/services/assessment/TestScenarioEngine.d.ts +9 -1
  22. package/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -1
  23. package/lib/services/assessment/TestScenarioEngine.js +17 -14
  24. package/lib/services/assessment/ToolClassifier.d.ts +154 -27
  25. package/lib/services/assessment/ToolClassifier.d.ts.map +1 -1
  26. package/lib/services/assessment/ToolClassifier.js +171 -318
  27. package/lib/services/assessment/config/annotationPatterns.d.ts +3 -1
  28. package/lib/services/assessment/config/annotationPatterns.d.ts.map +1 -1
  29. package/lib/services/assessment/config/annotationPatterns.js +5 -2
  30. package/lib/services/assessment/config/architecturePatterns.d.ts +101 -0
  31. package/lib/services/assessment/config/architecturePatterns.d.ts.map +1 -0
  32. package/lib/services/assessment/config/architecturePatterns.js +248 -0
  33. package/lib/services/assessment/config/performanceConfig.d.ts +122 -0
  34. package/lib/services/assessment/config/performanceConfig.d.ts.map +1 -0
  35. package/lib/services/assessment/config/performanceConfig.js +154 -0
  36. package/lib/services/assessment/config/sanitizationPatterns.d.ts +63 -0
  37. package/lib/services/assessment/config/sanitizationPatterns.d.ts.map +1 -0
  38. package/lib/services/assessment/config/sanitizationPatterns.js +223 -0
  39. package/lib/services/assessment/lib/claudeCodeBridge.d.ts +3 -1
  40. package/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -1
  41. package/lib/services/assessment/lib/claudeCodeBridge.js +5 -3
  42. package/lib/services/assessment/lib/concurrencyLimit.d.ts +6 -2
  43. package/lib/services/assessment/lib/concurrencyLimit.d.ts.map +1 -1
  44. package/lib/services/assessment/lib/concurrencyLimit.js +13 -6
  45. package/lib/services/assessment/lib/errors.d.ts +90 -0
  46. package/lib/services/assessment/lib/errors.d.ts.map +1 -0
  47. package/lib/services/assessment/lib/errors.js +136 -0
  48. package/lib/services/assessment/lib/timeoutUtils.d.ts +69 -0
  49. package/lib/services/assessment/lib/timeoutUtils.d.ts.map +1 -0
  50. package/lib/services/assessment/lib/timeoutUtils.js +103 -0
  51. package/lib/services/assessment/modules/BaseAssessor.d.ts +43 -8
  52. package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -1
  53. package/lib/services/assessment/modules/BaseAssessor.js +103 -34
  54. package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts +38 -1
  55. package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts.map +1 -1
  56. package/lib/services/assessment/modules/DeveloperExperienceAssessor.js +185 -19
  57. package/lib/services/assessment/modules/DocumentationAssessor.d.ts +5 -0
  58. package/lib/services/assessment/modules/DocumentationAssessor.d.ts.map +1 -1
  59. package/lib/services/assessment/modules/DocumentationAssessor.js +11 -0
  60. package/lib/services/assessment/modules/ErrorHandlingAssessor.js +1 -1
  61. package/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -1
  62. package/lib/services/assessment/modules/FunctionalityAssessor.js +6 -3
  63. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts +3 -0
  64. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -1
  65. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +14 -2
  66. package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
  67. package/lib/services/assessment/modules/ManifestValidationAssessor.js +7 -2
  68. package/lib/services/assessment/modules/PromptAssessor.d.ts +1 -0
  69. package/lib/services/assessment/modules/PromptAssessor.d.ts.map +1 -1
  70. package/lib/services/assessment/modules/PromptAssessor.js +26 -16
  71. package/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
  72. package/lib/services/assessment/modules/ProtocolComplianceAssessor.js +6 -2
  73. package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts +5 -0
  74. package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts.map +1 -1
  75. package/lib/services/assessment/modules/ProtocolConformanceAssessor.js +15 -0
  76. package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
  77. package/lib/services/assessment/modules/ResourceAssessor.js +8 -2
  78. package/lib/services/assessment/modules/SecurityAssessor.d.ts +3 -171
  79. package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
  80. package/lib/services/assessment/modules/SecurityAssessor.js +25 -1480
  81. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +27 -28
  82. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
  83. package/lib/services/assessment/modules/ToolAnnotationAssessor.js +340 -863
  84. package/lib/services/assessment/modules/UsabilityAssessor.d.ts +5 -0
  85. package/lib/services/assessment/modules/UsabilityAssessor.d.ts.map +1 -1
  86. package/lib/services/assessment/modules/UsabilityAssessor.js +11 -0
  87. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts +57 -0
  88. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts.map +1 -0
  89. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.js +176 -0
  90. package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts +67 -0
  91. package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts.map +1 -0
  92. package/lib/services/assessment/modules/annotations/ArchitectureDetector.js +239 -0
  93. package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts +46 -0
  94. package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts.map +1 -0
  95. package/lib/services/assessment/modules/annotations/BehaviorInference.js +394 -0
  96. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts +64 -0
  97. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts.map +1 -0
  98. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.js +304 -0
  99. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts +43 -0
  100. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -0
  101. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +276 -0
  102. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts +122 -0
  103. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts.map +1 -0
  104. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.js +388 -0
  105. package/lib/services/assessment/modules/annotations/index.d.ts +13 -0
  106. package/lib/services/assessment/modules/annotations/index.d.ts.map +1 -0
  107. package/lib/services/assessment/modules/annotations/index.js +15 -0
  108. package/lib/services/assessment/modules/index.d.ts +10 -0
  109. package/lib/services/assessment/modules/index.d.ts.map +1 -1
  110. package/lib/services/assessment/modules/index.js +13 -0
  111. package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts +125 -0
  112. package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts.map +1 -0
  113. package/lib/services/assessment/modules/securityTests/SanitizationDetector.js +345 -0
  114. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts +33 -0
  115. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -0
  116. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +128 -0
  117. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts +67 -0
  118. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -0
  119. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +372 -0
  120. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +178 -0
  121. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -0
  122. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +1207 -0
  123. package/lib/services/assessment/modules/securityTests/index.d.ts +8 -0
  124. package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -0
  125. package/lib/services/assessment/modules/securityTests/index.js +7 -0
  126. package/lib/services/assessment/orchestratorHelpers.d.ts +83 -0
  127. package/lib/services/assessment/orchestratorHelpers.d.ts.map +1 -0
  128. package/lib/services/assessment/orchestratorHelpers.js +212 -0
  129. package/lib/services/assessment/tool-classifier-patterns.d.ts +85 -0
  130. package/lib/services/assessment/tool-classifier-patterns.d.ts.map +1 -0
  131. package/lib/services/assessment/tool-classifier-patterns.js +365 -0
  132. 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, "&lt;")
309
+ .replace(/>/g, "&gt;");
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, "&amp;")
317
+ .replace(/</g, "&lt;")
318
+ .replace(/>/g, "&gt;")
319
+ .replace(/"/g, "&quot;")
320
+ .replace(/'/g, "&#x27;");
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
+ }