visus-mcp 0.3.0 → 0.6.0

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 (96) hide show
  1. package/.claude/settings.local.json +22 -0
  2. package/LINKEDIN-STRATEGY.md +367 -0
  3. package/README.md +491 -16
  4. package/ROADMAP.md +167 -30
  5. package/SECURITY-AUDIT-v1.md +277 -0
  6. package/STATUS.md +801 -42
  7. package/TROUBLESHOOT-AUTH-20260322-2019.md +291 -0
  8. package/TROUBLESHOOT-JEST-20260323-1357.md +139 -0
  9. package/TROUBLESHOOT-LAMBDA-20260322-1945.md +183 -0
  10. package/VISUS-CLAUDE-CODE-PROMPT.md +1 -1
  11. package/VISUS-PROJECT-PLAN.md +7 -0
  12. package/dist/browser/playwright-renderer.d.ts.map +1 -1
  13. package/dist/browser/playwright-renderer.js +7 -0
  14. package/dist/browser/playwright-renderer.js.map +1 -1
  15. package/dist/browser/reader.d.ts +31 -0
  16. package/dist/browser/reader.d.ts.map +1 -0
  17. package/dist/browser/reader.js +98 -0
  18. package/dist/browser/reader.js.map +1 -0
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +37 -5
  22. package/dist/index.js.map +1 -1
  23. package/dist/lambda-handler.d.ts +0 -6
  24. package/dist/lambda-handler.d.ts.map +1 -1
  25. package/dist/lambda-handler.js +97 -25
  26. package/dist/lambda-handler.js.map +1 -1
  27. package/dist/sanitizer/framework-mapper.d.ts +22 -0
  28. package/dist/sanitizer/framework-mapper.d.ts.map +1 -0
  29. package/dist/sanitizer/framework-mapper.js +296 -0
  30. package/dist/sanitizer/framework-mapper.js.map +1 -0
  31. package/dist/sanitizer/index.d.ts +2 -0
  32. package/dist/sanitizer/index.d.ts.map +1 -1
  33. package/dist/sanitizer/index.js +14 -1
  34. package/dist/sanitizer/index.js.map +1 -1
  35. package/dist/sanitizer/patterns.js +1 -1
  36. package/dist/sanitizer/patterns.js.map +1 -1
  37. package/dist/sanitizer/severity-classifier.d.ts +33 -0
  38. package/dist/sanitizer/severity-classifier.d.ts.map +1 -0
  39. package/dist/sanitizer/severity-classifier.js +113 -0
  40. package/dist/sanitizer/severity-classifier.js.map +1 -0
  41. package/dist/sanitizer/threat-reporter.d.ts +65 -0
  42. package/dist/sanitizer/threat-reporter.d.ts.map +1 -0
  43. package/dist/sanitizer/threat-reporter.js +160 -0
  44. package/dist/sanitizer/threat-reporter.js.map +1 -0
  45. package/dist/tools/fetch-structured.d.ts +5 -0
  46. package/dist/tools/fetch-structured.d.ts.map +1 -1
  47. package/dist/tools/fetch-structured.js +54 -6
  48. package/dist/tools/fetch-structured.js.map +1 -1
  49. package/dist/tools/fetch.d.ts +5 -0
  50. package/dist/tools/fetch.d.ts.map +1 -1
  51. package/dist/tools/fetch.js +42 -9
  52. package/dist/tools/fetch.js.map +1 -1
  53. package/dist/tools/read.d.ts +51 -0
  54. package/dist/tools/read.d.ts.map +1 -0
  55. package/dist/tools/read.js +127 -0
  56. package/dist/tools/read.js.map +1 -0
  57. package/dist/tools/search.d.ts +45 -0
  58. package/dist/tools/search.d.ts.map +1 -0
  59. package/dist/tools/search.js +220 -0
  60. package/dist/tools/search.js.map +1 -0
  61. package/dist/types.d.ts +64 -0
  62. package/dist/types.d.ts.map +1 -1
  63. package/dist/types.js.map +1 -1
  64. package/dist/utils/format-converter.d.ts +39 -0
  65. package/dist/utils/format-converter.d.ts.map +1 -0
  66. package/dist/utils/format-converter.js +191 -0
  67. package/dist/utils/format-converter.js.map +1 -0
  68. package/dist/utils/truncate.d.ts +26 -0
  69. package/dist/utils/truncate.d.ts.map +1 -0
  70. package/dist/utils/truncate.js +54 -0
  71. package/dist/utils/truncate.js.map +1 -0
  72. package/infrastructure/stack.ts +55 -6
  73. package/jest.config.js +3 -0
  74. package/package.json +9 -2
  75. package/src/browser/playwright-renderer.ts +8 -0
  76. package/src/browser/reader.ts +129 -0
  77. package/src/index.ts +49 -5
  78. package/src/lambda-handler.ts +131 -26
  79. package/src/sanitizer/framework-mapper.ts +347 -0
  80. package/src/sanitizer/index.ts +18 -1
  81. package/src/sanitizer/patterns.ts +1 -1
  82. package/src/sanitizer/severity-classifier.ts +132 -0
  83. package/src/sanitizer/threat-reporter.ts +261 -0
  84. package/src/tools/fetch-structured.ts +58 -6
  85. package/src/tools/fetch.ts +44 -9
  86. package/src/tools/read.ts +143 -0
  87. package/src/tools/search.ts +263 -0
  88. package/src/types.ts +69 -0
  89. package/src/utils/format-converter.ts +236 -0
  90. package/src/utils/truncate.ts +64 -0
  91. package/tests/auth-smoke.test.ts +480 -0
  92. package/tests/fetch-tool.test.ts +595 -2
  93. package/tests/reader.test.ts +353 -0
  94. package/tests/sanitizer.test.ts +52 -0
  95. package/tests/search.test.ts +456 -0
  96. package/tests/threat-reporter.test.ts +266 -0
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Compliance Framework Mapper
3
+ *
4
+ * Maps injection pattern categories to compliance framework identifiers:
5
+ * - OWASP LLM Top 10 (2025)
6
+ * - NIST AI 600-1 (Generative AI Profile)
7
+ * - MITRE ATLAS (Adversarial Threat Landscape for AI Systems)
8
+ */
9
+
10
+ export interface FrameworkMappings {
11
+ owasp_llm: string;
12
+ nist_ai_600_1: string;
13
+ mitre_atlas: string;
14
+ }
15
+
16
+ /**
17
+ * Pattern category to framework mapping
18
+ */
19
+ const FRAMEWORK_MAP: Record<string, FrameworkMappings> = {
20
+ // Direct instruction injection
21
+ direct_instruction_injection: {
22
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
23
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
24
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
25
+ },
26
+
27
+ // Role hijacking
28
+ role_hijacking: {
29
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
30
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
31
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
32
+ },
33
+
34
+ // System prompt extraction
35
+ system_prompt_extraction: {
36
+ owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
37
+ nist_ai_600_1: 'MS-2.6 - Data Disclosure',
38
+ mitre_atlas: 'AML.T0048 - External Harms'
39
+ },
40
+
41
+ // Privilege escalation
42
+ privilege_escalation: {
43
+ owasp_llm: 'LLM08:2025 - Excessive Agency',
44
+ nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
45
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
46
+ },
47
+
48
+ // Context poisoning
49
+ context_poisoning: {
50
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
51
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
52
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
53
+ },
54
+
55
+ // Data exfiltration
56
+ data_exfiltration: {
57
+ owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
58
+ nist_ai_600_1: 'MS-2.6 - Data Disclosure',
59
+ mitre_atlas: 'AML.T0048 - External Harms'
60
+ },
61
+
62
+ // Encoding obfuscation
63
+ base64_obfuscation: {
64
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
65
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
66
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
67
+ },
68
+
69
+ // Unicode lookalikes
70
+ unicode_lookalikes: {
71
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
72
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
73
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
74
+ },
75
+
76
+ // Zero-width characters
77
+ zero_width_characters: {
78
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
79
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
80
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
81
+ },
82
+
83
+ // HTML script injection
84
+ html_script_injection: {
85
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
86
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
87
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
88
+ },
89
+
90
+ // Data URI injection
91
+ data_uri_injection: {
92
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
93
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
94
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
95
+ },
96
+
97
+ // Markdown link injection
98
+ markdown_link_injection: {
99
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
100
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
101
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
102
+ },
103
+
104
+ // URL fragment attacks
105
+ url_fragment_hashjack: {
106
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
107
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
108
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
109
+ },
110
+
111
+ // Social engineering
112
+ social_engineering_urgency: {
113
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
114
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
115
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
116
+ },
117
+
118
+ // Instruction delimiter injection
119
+ instruction_delimiter_injection: {
120
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
121
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
122
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
123
+ },
124
+
125
+ // Multi-language obfuscation
126
+ multi_language_obfuscation: {
127
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
128
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
129
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
130
+ },
131
+
132
+ // Reverse text obfuscation
133
+ reverse_text_obfuscation: {
134
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
135
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
136
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
137
+ },
138
+
139
+ // Leetspeak obfuscation
140
+ leetspeak_obfuscation: {
141
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
142
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
143
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
144
+ },
145
+
146
+ // Jailbreak keywords
147
+ jailbreak_keywords: {
148
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
149
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
150
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
151
+ },
152
+
153
+ // Token smuggling
154
+ token_smuggling: {
155
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
156
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
157
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
158
+ },
159
+
160
+ // System message injection
161
+ system_message_injection: {
162
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
163
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
164
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
165
+ },
166
+
167
+ // Conversation reset
168
+ conversation_reset: {
169
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
170
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
171
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
172
+ },
173
+
174
+ // Memory manipulation
175
+ memory_manipulation: {
176
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
177
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
178
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
179
+ },
180
+
181
+ // Capability probing
182
+ capability_probing: {
183
+ owasp_llm: 'LLM08:2025 - Excessive Agency',
184
+ nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
185
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
186
+ },
187
+
188
+ // Chain-of-thought manipulation
189
+ chain_of_thought_manipulation: {
190
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
191
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
192
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
193
+ },
194
+
195
+ // Hypothetical scenario injection
196
+ hypothetical_scenario_injection: {
197
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
198
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
199
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
200
+ },
201
+
202
+ // Ethical override
203
+ ethical_override: {
204
+ owasp_llm: 'LLM08:2025 - Excessive Agency',
205
+ nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
206
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
207
+ },
208
+
209
+ // Output format manipulation
210
+ output_format_manipulation: {
211
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
212
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
213
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
214
+ },
215
+
216
+ // Negative instruction
217
+ negative_instruction: {
218
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
219
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
220
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
221
+ },
222
+
223
+ // Credential harvesting
224
+ credential_harvesting: {
225
+ owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
226
+ nist_ai_600_1: 'MS-2.6 - Data Disclosure',
227
+ mitre_atlas: 'AML.T0048 - External Harms'
228
+ },
229
+
230
+ // Time-based triggers
231
+ time_based_triggers: {
232
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
233
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
234
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
235
+ },
236
+
237
+ // Code execution requests
238
+ code_execution_requests: {
239
+ owasp_llm: 'LLM08:2025 - Excessive Agency',
240
+ nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
241
+ mitre_atlas: 'AML.T0048 - External Harms'
242
+ },
243
+
244
+ // File system access
245
+ file_system_access: {
246
+ owasp_llm: 'LLM08:2025 - Excessive Agency',
247
+ nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
248
+ mitre_atlas: 'AML.T0048 - External Harms'
249
+ },
250
+
251
+ // Training data extraction
252
+ training_data_extraction: {
253
+ owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
254
+ nist_ai_600_1: 'MS-2.6 - Data Disclosure',
255
+ mitre_atlas: 'AML.T0048 - External Harms'
256
+ },
257
+
258
+ // Simulator mode
259
+ simulator_mode: {
260
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
261
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
262
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
263
+ },
264
+
265
+ // Nested encoding
266
+ nested_encoding: {
267
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
268
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
269
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
270
+ },
271
+
272
+ // Payload splitting
273
+ payload_splitting: {
274
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
275
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
276
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
277
+ },
278
+
279
+ // CSS-based hiding
280
+ css_hiding: {
281
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
282
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
283
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
284
+ },
285
+
286
+ // Authority impersonation
287
+ authority_impersonation: {
288
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
289
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
290
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
291
+ },
292
+
293
+ // Testing/debugging claims
294
+ testing_debugging_claims: {
295
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
296
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
297
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
298
+ },
299
+
300
+ // Callback URL injection
301
+ callback_url_injection: {
302
+ owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
303
+ nist_ai_600_1: 'MS-2.6 - Data Disclosure',
304
+ mitre_atlas: 'AML.T0048 - External Harms'
305
+ },
306
+
307
+ // Whitespace steganography
308
+ whitespace_steganography: {
309
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
310
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
311
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
312
+ },
313
+
314
+ // Comment injection
315
+ comment_injection: {
316
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
317
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
318
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
319
+ }
320
+ };
321
+
322
+ /**
323
+ * Default mapping for unknown pattern categories
324
+ */
325
+ const DEFAULT_MAPPINGS: FrameworkMappings = {
326
+ owasp_llm: 'LLM01:2025 - Prompt Injection',
327
+ nist_ai_600_1: 'MS-2.5 - Prompt Injection',
328
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
329
+ };
330
+
331
+ /**
332
+ * Get framework mappings for a pattern category
333
+ */
334
+ export function getFrameworkMappings(patternCategory: string): FrameworkMappings {
335
+ return FRAMEWORK_MAP[patternCategory] || DEFAULT_MAPPINGS;
336
+ }
337
+
338
+ /**
339
+ * Get all supported frameworks
340
+ */
341
+ export function getSupportedFrameworks(): string[] {
342
+ return [
343
+ 'OWASP LLM Top 10 (2025)',
344
+ 'NIST AI 600-1 (Generative AI Profile)',
345
+ 'MITRE ATLAS (Adversarial Threat Landscape)'
346
+ ];
347
+ }
@@ -10,6 +10,7 @@
10
10
 
11
11
  import { detectAndNeutralize, getSeverityScore, hasCriticalThreats } from './injection-detector.js';
12
12
  import { redactPII } from './pii-redactor.js';
13
+ import { generateThreatReport, type ThreatReport } from './threat-reporter.js';
13
14
 
14
15
  export interface SanitizationResult {
15
16
  content: string;
@@ -31,6 +32,7 @@ export interface SanitizationResult {
31
32
  low: number;
32
33
  };
33
34
  };
35
+ threat_report?: ThreatReport;
34
36
  }
35
37
 
36
38
  /**
@@ -71,7 +73,15 @@ export function sanitize(content: string, sourceUrl?: string): SanitizationResul
71
73
  content_modified: contentModified
72
74
  });
73
75
 
74
- return {
76
+ // Step 4: Generate threat report (only if findings exist)
77
+ const threatReport = generateThreatReport({
78
+ patterns_detected: injectionResult.patterns_detected,
79
+ pii_redacted: piiResult.pii_types_redacted.length,
80
+ source_url: sourceUrl || 'unknown',
81
+ detections_by_severity: injectionResult.metadata.detections_by_severity
82
+ });
83
+
84
+ const result: SanitizationResult = {
75
85
  content: finalContent,
76
86
  sanitization: {
77
87
  patterns_detected: injectionResult.patterns_detected,
@@ -87,6 +97,13 @@ export function sanitize(content: string, sourceUrl?: string): SanitizationResul
87
97
  detections_by_severity: injectionResult.metadata.detections_by_severity
88
98
  }
89
99
  };
100
+
101
+ // Include threat_report only if findings exist
102
+ if (threatReport) {
103
+ result.threat_report = threatReport;
104
+ }
105
+
106
+ return result;
90
107
  }
91
108
 
92
109
  /**
@@ -313,7 +313,7 @@ export const INJECTION_PATTERNS: InjectionPattern[] = [
313
313
  {
314
314
  name: 'code_execution_requests',
315
315
  description: 'Requests code execution or contains dangerous code patterns',
316
- regex: /\b(execute|run\s+the\s+following|eval\(|exec\(|os\.system|subprocess|__import__|shell\s+command|bash\s+-c)\b/gi,
316
+ regex: /\b(execute(?!-api\.)|run\s+the\s+following|eval\(|exec\(|os\.system|subprocess|__import__|shell\s+command|bash\s+-c)\b/gi,
317
317
  severity: 'high',
318
318
  action: 'redact'
319
319
  },
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Severity Classification Engine
3
+ *
4
+ * Maps injection pattern categories to standardized severity levels.
5
+ * Used for threat reporting and compliance documentation.
6
+ */
7
+
8
+ export type Severity = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW';
9
+ export type OverallSeverity = Severity | 'CLEAN';
10
+
11
+ /**
12
+ * Pattern category to severity mapping
13
+ * Aligned with NIST AI 600-1 and OWASP LLM Top 10 risk levels
14
+ */
15
+ const SEVERITY_MAP: Record<string, Severity> = {
16
+ // CRITICAL - Immediate threat, block-level
17
+ direct_instruction_injection: 'CRITICAL',
18
+ role_hijacking: 'CRITICAL',
19
+ system_prompt_extraction: 'CRITICAL',
20
+ privilege_escalation: 'CRITICAL',
21
+ data_exfiltration: 'CRITICAL',
22
+ code_execution_requests: 'CRITICAL',
23
+ memory_manipulation: 'CRITICAL',
24
+ jailbreak_keywords: 'CRITICAL',
25
+ ethical_override: 'CRITICAL',
26
+ credential_harvesting: 'CRITICAL',
27
+ html_script_injection: 'CRITICAL',
28
+
29
+ // HIGH - Significant threat
30
+ context_poisoning: 'HIGH',
31
+ base64_obfuscation: 'HIGH',
32
+ zero_width_characters: 'HIGH',
33
+ data_uri_injection: 'HIGH',
34
+ markdown_link_injection: 'HIGH',
35
+ instruction_delimiter_injection: 'HIGH',
36
+ token_smuggling: 'HIGH',
37
+ system_message_injection: 'HIGH',
38
+ file_system_access: 'HIGH',
39
+ training_data_extraction: 'HIGH',
40
+ nested_encoding: 'HIGH',
41
+ authority_impersonation: 'HIGH',
42
+ callback_url_injection: 'HIGH',
43
+
44
+ // MEDIUM - Moderate threat
45
+ comment_injection: 'MEDIUM',
46
+ unicode_lookalikes: 'MEDIUM',
47
+ url_fragment_hashjack: 'MEDIUM',
48
+ social_engineering_urgency: 'MEDIUM',
49
+ multi_language_obfuscation: 'MEDIUM',
50
+ reverse_text_obfuscation: 'MEDIUM',
51
+ conversation_reset: 'MEDIUM',
52
+ chain_of_thought_manipulation: 'MEDIUM',
53
+ hypothetical_scenario_injection: 'MEDIUM',
54
+ output_format_manipulation: 'MEDIUM',
55
+ simulator_mode: 'MEDIUM',
56
+ payload_splitting: 'MEDIUM',
57
+ css_hiding: 'MEDIUM',
58
+ testing_debugging_claims: 'MEDIUM',
59
+
60
+ // LOW - Low threat, flagged for awareness
61
+ leetspeak_obfuscation: 'LOW',
62
+ capability_probing: 'LOW',
63
+ negative_instruction: 'LOW',
64
+ time_based_triggers: 'LOW',
65
+ whitespace_steganography: 'LOW'
66
+ };
67
+
68
+ /**
69
+ * Classify severity for a single pattern category
70
+ */
71
+ export function classifySeverity(patternCategory: string): Severity {
72
+ return SEVERITY_MAP[patternCategory] || 'LOW';
73
+ }
74
+
75
+ /**
76
+ * Interface for a threat finding
77
+ */
78
+ export interface Finding {
79
+ pattern_category: string;
80
+ severity: Severity;
81
+ }
82
+
83
+ /**
84
+ * Aggregate severity across multiple findings
85
+ * Returns the highest severity level found, or CLEAN if no findings
86
+ */
87
+ export function aggregateSeverity(findings: Finding[]): OverallSeverity {
88
+ if (findings.length === 0) {
89
+ return 'CLEAN';
90
+ }
91
+
92
+ const severities = findings.map(f => f.severity);
93
+
94
+ if (severities.includes('CRITICAL')) return 'CRITICAL';
95
+ if (severities.includes('HIGH')) return 'HIGH';
96
+ if (severities.includes('MEDIUM')) return 'MEDIUM';
97
+ if (severities.includes('LOW')) return 'LOW';
98
+
99
+ return 'CLEAN';
100
+ }
101
+
102
+ /**
103
+ * Count findings by severity level
104
+ */
105
+ export function countBySeverity(findings: Finding[]): Record<Severity, number> {
106
+ const counts: Record<Severity, number> = {
107
+ CRITICAL: 0,
108
+ HIGH: 0,
109
+ MEDIUM: 0,
110
+ LOW: 0
111
+ };
112
+
113
+ for (const finding of findings) {
114
+ counts[finding.severity]++;
115
+ }
116
+
117
+ return counts;
118
+ }
119
+
120
+ /**
121
+ * Get emoji for severity level (for Markdown reports)
122
+ */
123
+ export function getSeverityEmoji(severity: Severity | OverallSeverity): string {
124
+ switch (severity) {
125
+ case 'CRITICAL': return '🔴';
126
+ case 'HIGH': return '🟠';
127
+ case 'MEDIUM': return '🟡';
128
+ case 'LOW': return '🟢';
129
+ case 'CLEAN': return '✅';
130
+ default: return '⚪';
131
+ }
132
+ }