@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,304 @@
1
+ /**
2
+ * Description Analyzer
3
+ *
4
+ * Analyzes tool descriptions for behavioral keywords to infer expected behavior.
5
+ * This provides a more robust inference than name-pattern matching alone.
6
+ *
7
+ * Part of Issue #57: Architecture detection and behavior inference modules
8
+ */
9
+ /**
10
+ * Keyword categories with confidence levels.
11
+ * Keywords in 'high' have strong semantic association with the behavior.
12
+ * Keywords in 'medium' are indicative but may have context-dependent meanings.
13
+ * Keywords in 'low' are weak indicators.
14
+ */
15
+ export const DESCRIPTION_BEHAVIOR_KEYWORDS = {
16
+ readOnly: {
17
+ high: [
18
+ "retrieves",
19
+ "returns",
20
+ "lists",
21
+ "shows",
22
+ "displays",
23
+ "queries",
24
+ "searches",
25
+ "finds",
26
+ "looks up",
27
+ "fetches",
28
+ ],
29
+ medium: [
30
+ "gets",
31
+ "reads",
32
+ "views",
33
+ "checks",
34
+ "verifies",
35
+ "validates",
36
+ "inspects",
37
+ "examines",
38
+ "browses",
39
+ "previews",
40
+ ],
41
+ low: [
42
+ "accesses",
43
+ "obtains",
44
+ "provides",
45
+ "outputs",
46
+ "prints",
47
+ "counts",
48
+ "measures",
49
+ "calculates",
50
+ ],
51
+ },
52
+ destructive: {
53
+ high: [
54
+ "deletes",
55
+ "removes",
56
+ "destroys",
57
+ "drops",
58
+ "purges",
59
+ "wipes",
60
+ "clears",
61
+ "erases",
62
+ "permanently",
63
+ "irreversible",
64
+ "archives", // soft-delete euphemism
65
+ "terminated", // forceful process ending
66
+ ],
67
+ medium: [
68
+ "truncates",
69
+ "kills",
70
+ "terminates",
71
+ "revokes",
72
+ "cancels",
73
+ "uninstalls",
74
+ "dismounts",
75
+ "detaches",
76
+ "marks", // when combined with deleted/archived
77
+ ],
78
+ low: ["resets", "restores to default", "cleans", "cleanup"],
79
+ },
80
+ write: {
81
+ high: [
82
+ "creates",
83
+ "inserts",
84
+ "adds",
85
+ "generates",
86
+ "produces",
87
+ "makes",
88
+ "builds",
89
+ ],
90
+ medium: [
91
+ "updates",
92
+ "modifies",
93
+ "changes",
94
+ "edits",
95
+ "sets",
96
+ "puts",
97
+ "patches",
98
+ "appends",
99
+ "extends",
100
+ "increments", // modify operation
101
+ "decrements", // modify operation
102
+ ],
103
+ low: [
104
+ "saves",
105
+ "stores",
106
+ "writes",
107
+ "posts",
108
+ "sends",
109
+ "submits",
110
+ "publishes",
111
+ "uploads",
112
+ "exports",
113
+ ],
114
+ },
115
+ };
116
+ /**
117
+ * Negation patterns that might invert the meaning of keywords.
118
+ * E.g., "does not delete" should not be marked as destructive.
119
+ */
120
+ const NEGATION_PATTERNS = [
121
+ /\b(does\s+not|doesn't|do\s+not|don't|cannot|can't|will\s+not|won't|never|without)\s+/i,
122
+ /\bnot\s+(delete|remove|destroy|modify|change|create|update)/i,
123
+ ];
124
+ /**
125
+ * Threshold for write signals to override read-only classification.
126
+ * Write signals at 50%+ of read-only score indicate mixed operation tools
127
+ * (e.g., "fetch and update" should classify as write, not read-only).
128
+ */
129
+ const WRITE_OVERRIDE_THRESHOLD = 0.5;
130
+ /**
131
+ * Check if a keyword match is negated by surrounding context.
132
+ *
133
+ * @param description - Full description text
134
+ * @param keywordIndex - Index where keyword was found
135
+ * @param windowSize - Characters before keyword to check for negation
136
+ * @returns True if the keyword is negated
137
+ */
138
+ function isNegated(description, keywordIndex, windowSize = 60) {
139
+ const start = Math.max(0, keywordIndex - windowSize);
140
+ const contextBefore = description.slice(start, keywordIndex);
141
+ for (const pattern of NEGATION_PATTERNS) {
142
+ if (pattern.test(contextBefore)) {
143
+ return true;
144
+ }
145
+ }
146
+ return false;
147
+ }
148
+ /**
149
+ * Find keyword matches in description with confidence levels.
150
+ *
151
+ * @param description - Tool description to analyze
152
+ * @param keywords - Keyword object with high/medium/low arrays
153
+ * @returns Array of matches with confidence scores
154
+ */
155
+ function findKeywordMatches(description, keywords) {
156
+ const matches = [];
157
+ const lowerDesc = description.toLowerCase();
158
+ const searchKeywords = (keywordList, confidence) => {
159
+ for (const keyword of keywordList) {
160
+ // Create a regex pattern that matches the keyword as a word
161
+ const pattern = new RegExp(`\\b${keyword.replace(/\s+/g, "\\s+")}`, "gi");
162
+ let match;
163
+ while ((match = pattern.exec(lowerDesc)) !== null) {
164
+ const negated = isNegated(lowerDesc, match.index);
165
+ matches.push({ keyword, confidence, negated });
166
+ }
167
+ }
168
+ };
169
+ searchKeywords(keywords.high, 90);
170
+ searchKeywords(keywords.medium, 70);
171
+ searchKeywords(keywords.low, 50);
172
+ return matches;
173
+ }
174
+ /**
175
+ * Analyze a tool description for behavioral signals.
176
+ *
177
+ * @param description - Tool description to analyze
178
+ * @returns InferenceSignal with read-only/destructive expectations
179
+ */
180
+ export function analyzeDescription(description) {
181
+ if (!description || description.trim().length === 0) {
182
+ return {
183
+ expectedReadOnly: false,
184
+ expectedDestructive: false,
185
+ confidence: 0,
186
+ evidence: ["No description provided"],
187
+ };
188
+ }
189
+ // Find all keyword matches for each category
190
+ const readOnlyMatches = findKeywordMatches(description, DESCRIPTION_BEHAVIOR_KEYWORDS.readOnly);
191
+ const destructiveMatches = findKeywordMatches(description, DESCRIPTION_BEHAVIOR_KEYWORDS.destructive);
192
+ const writeMatches = findKeywordMatches(description, DESCRIPTION_BEHAVIOR_KEYWORDS.write);
193
+ // Filter out negated matches for the primary behavior classification
194
+ const activeReadOnly = readOnlyMatches.filter((m) => !m.negated);
195
+ const activeDestructive = destructiveMatches.filter((m) => !m.negated);
196
+ const activeWrite = writeMatches.filter((m) => !m.negated);
197
+ // Calculate weighted scores for each category
198
+ const readOnlyScore = activeReadOnly.reduce((sum, m) => sum + m.confidence, 0);
199
+ const destructiveScore = activeDestructive.reduce((sum, m) => sum + m.confidence, 0);
200
+ const writeScore = activeWrite.reduce((sum, m) => sum + m.confidence, 0);
201
+ // Determine the dominant behavior
202
+ const evidence = [];
203
+ let expectedReadOnly = false;
204
+ let expectedDestructive = false;
205
+ let confidence = 0;
206
+ // Destructive takes priority if detected with high confidence
207
+ if (destructiveScore > 0) {
208
+ expectedDestructive = true;
209
+ confidence = Math.min(100, destructiveScore);
210
+ evidence.push(`Destructive keywords: ${activeDestructive.map((m) => m.keyword).join(", ")}`);
211
+ }
212
+ // Read-only detection (only if not destructive)
213
+ if (readOnlyScore > 0 && !expectedDestructive) {
214
+ // Write operations take precedence when present (even if equal score)
215
+ // Multi-operation tools like "fetch and update" should be classified as write
216
+ if (writeScore > 0 &&
217
+ writeScore >= readOnlyScore * WRITE_OVERRIDE_THRESHOLD) {
218
+ // Write signal is significant enough to override read-only
219
+ confidence = Math.min(100, writeScore);
220
+ evidence.push(`Write keywords override read: ${activeWrite.map((m) => m.keyword).join(", ")}`);
221
+ }
222
+ else if (readOnlyScore > writeScore) {
223
+ expectedReadOnly = true;
224
+ confidence = Math.min(100, readOnlyScore);
225
+ evidence.push(`Read-only keywords: ${activeReadOnly.map((m) => m.keyword).join(", ")}`);
226
+ }
227
+ }
228
+ // Pure write operation (no read-only indicators)
229
+ if (!expectedReadOnly && !expectedDestructive && writeScore > 0) {
230
+ confidence = Math.min(100, writeScore);
231
+ evidence.push(`Write keywords: ${activeWrite.map((m) => m.keyword).join(", ")}`);
232
+ }
233
+ // Add negation evidence if present
234
+ const negatedKeywords = [
235
+ ...readOnlyMatches.filter((m) => m.negated),
236
+ ...destructiveMatches.filter((m) => m.negated),
237
+ ...writeMatches.filter((m) => m.negated),
238
+ ];
239
+ if (negatedKeywords.length > 0) {
240
+ evidence.push(`Negated keywords ignored: ${negatedKeywords.map((m) => m.keyword).join(", ")}`);
241
+ }
242
+ // Default case: no signals
243
+ if (evidence.length === 0) {
244
+ evidence.push("No behavioral keywords detected in description");
245
+ confidence = 0;
246
+ }
247
+ return {
248
+ expectedReadOnly,
249
+ expectedDestructive,
250
+ confidence,
251
+ evidence,
252
+ };
253
+ }
254
+ /**
255
+ * Quick check if description contains read-only indicators.
256
+ * Useful for fast filtering before full analysis.
257
+ *
258
+ * @param description - Tool description to check
259
+ * @returns True if any read-only keywords are present
260
+ */
261
+ export function hasReadOnlyIndicators(description) {
262
+ if (!description)
263
+ return false;
264
+ const lowerDesc = description.toLowerCase();
265
+ const allReadOnlyKeywords = [
266
+ ...DESCRIPTION_BEHAVIOR_KEYWORDS.readOnly.high,
267
+ ...DESCRIPTION_BEHAVIOR_KEYWORDS.readOnly.medium,
268
+ ];
269
+ return allReadOnlyKeywords.some((keyword) => lowerDesc.includes(keyword.toLowerCase()));
270
+ }
271
+ /**
272
+ * Quick check if description contains destructive indicators.
273
+ * Useful for fast filtering before full analysis.
274
+ *
275
+ * @param description - Tool description to check
276
+ * @returns True if any destructive keywords are present
277
+ */
278
+ export function hasDestructiveIndicators(description) {
279
+ if (!description)
280
+ return false;
281
+ const lowerDesc = description.toLowerCase();
282
+ const allDestructiveKeywords = [
283
+ ...DESCRIPTION_BEHAVIOR_KEYWORDS.destructive.high,
284
+ ...DESCRIPTION_BEHAVIOR_KEYWORDS.destructive.medium,
285
+ ];
286
+ return allDestructiveKeywords.some((keyword) => lowerDesc.includes(keyword.toLowerCase()));
287
+ }
288
+ /**
289
+ * Quick check if description contains write indicators.
290
+ * Useful for fast filtering before full analysis.
291
+ *
292
+ * @param description - Tool description to check
293
+ * @returns True if any write keywords are present
294
+ */
295
+ export function hasWriteIndicators(description) {
296
+ if (!description)
297
+ return false;
298
+ const lowerDesc = description.toLowerCase();
299
+ const allWriteKeywords = [
300
+ ...DESCRIPTION_BEHAVIOR_KEYWORDS.write.high,
301
+ ...DESCRIPTION_BEHAVIOR_KEYWORDS.write.medium,
302
+ ];
303
+ return allWriteKeywords.some((keyword) => lowerDesc.includes(keyword.toLowerCase()));
304
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Description Poisoning Detector
3
+ * Detects hidden instructions and malicious content in tool descriptions
4
+ *
5
+ * Extracted from ToolAnnotationAssessor.ts for maintainability.
6
+ * Issue #8 implementation.
7
+ */
8
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
9
+ /**
10
+ * Tool description poisoning pattern definition
11
+ */
12
+ export interface PoisoningPattern {
13
+ name: string;
14
+ pattern: RegExp;
15
+ severity: "LOW" | "MEDIUM" | "HIGH";
16
+ category: string;
17
+ }
18
+ /**
19
+ * Result of description poisoning scan
20
+ */
21
+ export interface PoisoningScanResult {
22
+ detected: boolean;
23
+ patterns: Array<{
24
+ name: string;
25
+ pattern: string;
26
+ severity: "LOW" | "MEDIUM" | "HIGH";
27
+ category: string;
28
+ evidence: string;
29
+ }>;
30
+ riskLevel: "NONE" | "LOW" | "MEDIUM" | "HIGH";
31
+ }
32
+ /**
33
+ * Description poisoning patterns for detecting malicious tool descriptions
34
+ * Covers: hidden instructions, override commands, concealment, exfiltration,
35
+ * delimiter injection, encoding bypass, and typoglycemia/evasion patterns
36
+ */
37
+ export declare const DESCRIPTION_POISONING_PATTERNS: PoisoningPattern[];
38
+ /**
39
+ * Scan tool description for poisoning patterns
40
+ * Detects hidden instructions, override commands, concealment, and exfiltration attempts
41
+ */
42
+ export declare function scanDescriptionForPoisoning(tool: Tool): PoisoningScanResult;
43
+ //# sourceMappingURL=DescriptionPoisoningDetector.d.ts.map
@@ -0,0 +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,EA2O5D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,IAAI,GAAG,mBAAmB,CA+C3E"}
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Description Poisoning Detector
3
+ * Detects hidden instructions and malicious content in tool descriptions
4
+ *
5
+ * Extracted from ToolAnnotationAssessor.ts for maintainability.
6
+ * Issue #8 implementation.
7
+ */
8
+ /**
9
+ * Description poisoning patterns for detecting malicious tool descriptions
10
+ * Covers: hidden instructions, override commands, concealment, exfiltration,
11
+ * delimiter injection, encoding bypass, and typoglycemia/evasion patterns
12
+ */
13
+ export const DESCRIPTION_POISONING_PATTERNS = [
14
+ // Hidden instruction tags
15
+ {
16
+ name: "hidden_tag",
17
+ pattern: /<HIDDEN>[\s\S]*?<\/HIDDEN>/gi,
18
+ severity: "HIGH",
19
+ category: "hidden_instructions",
20
+ },
21
+ {
22
+ name: "important_tag",
23
+ pattern: /<IMPORTANT>[\s\S]*?<\/IMPORTANT>/gi,
24
+ severity: "HIGH",
25
+ category: "hidden_instructions",
26
+ },
27
+ {
28
+ name: "system_tag",
29
+ pattern: /<SYSTEM>[\s\S]*?<\/SYSTEM>/gi,
30
+ severity: "HIGH",
31
+ category: "hidden_instructions",
32
+ },
33
+ {
34
+ name: "instruction_tag",
35
+ pattern: /<INSTRUCTION>[\s\S]*?<\/INSTRUCTION>/gi,
36
+ severity: "HIGH",
37
+ category: "hidden_instructions",
38
+ },
39
+ // Override commands
40
+ {
41
+ name: "ignore_instructions",
42
+ pattern: /ignore\s+(all\s+)?(previous|prior|above)\s+instructions/i,
43
+ severity: "HIGH",
44
+ category: "override",
45
+ },
46
+ {
47
+ name: "disregard_instructions",
48
+ pattern: /disregard\s+(all\s+)?(previous|prior)\s+instructions/i,
49
+ severity: "HIGH",
50
+ category: "override",
51
+ },
52
+ {
53
+ name: "you_are_now",
54
+ pattern: /you\s+are\s+now\s+(a|an|the)/i,
55
+ severity: "MEDIUM",
56
+ category: "override",
57
+ },
58
+ {
59
+ name: "system_override",
60
+ pattern: /system:\s*override/i,
61
+ severity: "HIGH",
62
+ category: "override",
63
+ },
64
+ // Secrecy/concealment
65
+ {
66
+ name: "do_not_mention",
67
+ pattern: /do\s+not\s+(mention|tell|inform|reveal)/i,
68
+ severity: "HIGH",
69
+ category: "concealment",
70
+ },
71
+ {
72
+ name: "secretly",
73
+ pattern: /\bsecretly\b/i,
74
+ severity: "MEDIUM",
75
+ category: "concealment",
76
+ },
77
+ {
78
+ name: "hide_from_user",
79
+ pattern: /hide\s+(this\s+)?from\s+(the\s+)?user/i,
80
+ severity: "HIGH",
81
+ category: "concealment",
82
+ },
83
+ // Data exfiltration
84
+ {
85
+ name: "return_keys",
86
+ pattern: /return\s+(all\s+)?(api\s*)?keys/i,
87
+ severity: "HIGH",
88
+ category: "exfiltration",
89
+ },
90
+ {
91
+ name: "include_credentials",
92
+ // More specific: requires directive context (in/with/when/to) to reduce false positives
93
+ pattern: /include\s+(the\s+|all\s+|your\s+)?(api.?key|credential|password|secret)s?\s*(in|with|when|to)/i,
94
+ severity: "HIGH",
95
+ category: "exfiltration",
96
+ },
97
+ {
98
+ name: "reveal_secrets",
99
+ pattern: /reveal\s+(all\s+)?(secrets|credentials|api\s*keys)/i,
100
+ severity: "HIGH",
101
+ category: "exfiltration",
102
+ },
103
+ {
104
+ name: "access_internal_secrets",
105
+ pattern: /access\s+(the\s+)?internal\s+(api\s*)?(key|secret|credential|password|token)/i,
106
+ severity: "HIGH",
107
+ category: "exfiltration",
108
+ },
109
+ // Delimiter injection
110
+ {
111
+ name: "system_codeblock",
112
+ pattern: /```system[\s\S]*?```/gi,
113
+ severity: "HIGH",
114
+ category: "delimiter",
115
+ },
116
+ {
117
+ name: "inst_tags",
118
+ pattern: /\[INST\][\s\S]*?\[\/INST\]/gi,
119
+ severity: "HIGH",
120
+ category: "delimiter",
121
+ },
122
+ {
123
+ name: "chatml_system",
124
+ pattern: /<\|im_start\|>system/gi,
125
+ severity: "HIGH",
126
+ category: "delimiter",
127
+ },
128
+ {
129
+ name: "llama_sys",
130
+ pattern: /<<SYS>>/gi,
131
+ severity: "HIGH",
132
+ category: "delimiter",
133
+ },
134
+ {
135
+ name: "user_assistant_block",
136
+ pattern: /\[USER\][\s\S]*?\[ASSISTANT\]/gi,
137
+ severity: "HIGH",
138
+ category: "delimiter",
139
+ },
140
+ // Role/persona injection (Warning #4)
141
+ {
142
+ name: "act_as",
143
+ pattern: /act\s+(like|as)\s+(a|an|the)/i,
144
+ severity: "MEDIUM",
145
+ category: "override",
146
+ },
147
+ {
148
+ name: "pretend_to_be",
149
+ pattern: /pretend\s+(to\s+be|you\s*'?re)/i,
150
+ severity: "MEDIUM",
151
+ category: "override",
152
+ },
153
+ {
154
+ name: "roleplay_as",
155
+ pattern: /role\s*play\s+(as|like)/i,
156
+ severity: "MEDIUM",
157
+ category: "override",
158
+ },
159
+ {
160
+ name: "new_task",
161
+ pattern: /new\s+(task|instruction|objective):\s*/i,
162
+ severity: "HIGH",
163
+ category: "override",
164
+ },
165
+ // Encoding bypass detection (Warning #1)
166
+ {
167
+ name: "base64_encoded_block",
168
+ pattern: /[A-Za-z0-9+/]{50,}={0,2}/g, // Large Base64 strings (50+ chars)
169
+ severity: "MEDIUM",
170
+ category: "encoding_bypass",
171
+ },
172
+ {
173
+ name: "unicode_escape_sequence",
174
+ pattern: /(?:\\u[0-9a-fA-F]{4}){3,}/gi, // 3+ consecutive Unicode escapes
175
+ severity: "MEDIUM",
176
+ category: "encoding_bypass",
177
+ },
178
+ {
179
+ name: "html_entity_block",
180
+ pattern: /(?:&#x?[0-9a-fA-F]+;){3,}/gi, // 3+ consecutive HTML entities
181
+ severity: "MEDIUM",
182
+ category: "encoding_bypass",
183
+ },
184
+ // Typoglycemia/evasion patterns (Warning #2)
185
+ {
186
+ name: "ignore_instructions_typo",
187
+ pattern: /ign[o0]r[e3]?\s+(all\s+)?(pr[e3]v[i1][o0]us|pr[i1][o0]r|ab[o0]v[e3])\s+[i1]nstruct[i1][o0]ns?/i,
188
+ severity: "HIGH",
189
+ category: "override",
190
+ },
191
+ {
192
+ name: "disregard_typo",
193
+ pattern: /d[i1]sr[e3]g[a4]rd\s+(all\s+)?(pr[e3]v[i1][o0]us|pr[i1][o0]r)\s+[i1]nstruct[i1][o0]ns?/i,
194
+ severity: "HIGH",
195
+ category: "override",
196
+ },
197
+ // DVMCP-specific patterns (CTF testbed coverage)
198
+ {
199
+ name: "override_auth_protocol",
200
+ pattern: /override[-_]?auth[-_]?protocol/gi,
201
+ severity: "HIGH",
202
+ category: "auth_bypass",
203
+ },
204
+ {
205
+ name: "internal_resource_uri",
206
+ pattern: /(?:internal|system|admin|secret|company|confidential):\/\/[a-z_\-/]+/gi,
207
+ severity: "HIGH",
208
+ category: "resource_access",
209
+ },
210
+ {
211
+ name: "get_secrets_call",
212
+ pattern: /get[-_]?secrets?\s*\(/gi,
213
+ severity: "HIGH",
214
+ category: "secret_access",
215
+ },
216
+ {
217
+ name: "master_password",
218
+ pattern: /master[-_]?password/gi,
219
+ severity: "HIGH",
220
+ category: "credential_exposure",
221
+ },
222
+ {
223
+ name: "access_confidential",
224
+ pattern: /access\s+(the\s+)?confidential/gi,
225
+ severity: "HIGH",
226
+ category: "exfiltration",
227
+ },
228
+ {
229
+ name: "hidden_trigger_phrase",
230
+ pattern: /if\s+(the\s+)?(query|input|text)\s+contains\s+(the\s+)?(exact\s+)?(phrase|word)/gi,
231
+ severity: "HIGH",
232
+ category: "hidden_trigger",
233
+ },
234
+ ];
235
+ /**
236
+ * Scan tool description for poisoning patterns
237
+ * Detects hidden instructions, override commands, concealment, and exfiltration attempts
238
+ */
239
+ export function scanDescriptionForPoisoning(tool) {
240
+ const description = tool.description || "";
241
+ const matches = [];
242
+ for (const patternDef of DESCRIPTION_POISONING_PATTERNS) {
243
+ // Create a fresh regex to reset lastIndex
244
+ const regex = new RegExp(patternDef.pattern.source, patternDef.pattern.flags);
245
+ // Loop to find all matches (not just first)
246
+ let match;
247
+ while ((match = regex.exec(description)) !== null) {
248
+ matches.push({
249
+ name: patternDef.name,
250
+ pattern: patternDef.pattern.toString(),
251
+ severity: patternDef.severity,
252
+ category: patternDef.category,
253
+ evidence: match[0].substring(0, 100) + (match[0].length > 100 ? "..." : ""),
254
+ });
255
+ // Prevent infinite loop for patterns without 'g' flag
256
+ if (!regex.global)
257
+ break;
258
+ }
259
+ }
260
+ // Determine overall risk level based on highest severity match
261
+ let riskLevel = "NONE";
262
+ if (matches.some((m) => m.severity === "HIGH")) {
263
+ riskLevel = "HIGH";
264
+ }
265
+ else if (matches.some((m) => m.severity === "MEDIUM")) {
266
+ riskLevel = "MEDIUM";
267
+ }
268
+ else if (matches.length > 0) {
269
+ riskLevel = "LOW";
270
+ }
271
+ return {
272
+ detected: matches.length > 0,
273
+ patterns: matches,
274
+ riskLevel,
275
+ };
276
+ }