visus-mcp 0.6.0 → 0.6.2

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 (147) hide show
  1. package/.claude/settings.local.json +42 -1
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +47 -0
  3. package/.github/ISSUE_TEMPLATE/false_positive.md +43 -0
  4. package/.github/ISSUE_TEMPLATE/new_pattern.md +49 -0
  5. package/.github/ISSUE_TEMPLATE/security_report.md +31 -0
  6. package/.github/PULL_REQUEST_TEMPLATE.md +39 -0
  7. package/.mcpregistry_github_token +1 -0
  8. package/.mcpregistry_registry_token +1 -0
  9. package/CLAUDE.md +197 -0
  10. package/CONTRIBUTING.md +329 -0
  11. package/README.md +111 -45
  12. package/STATUS.md +167 -29
  13. package/SUBMISSION.md +66 -0
  14. package/TROUBLESHOOT-COGNITO-AUTH-20260324-2029.md +415 -0
  15. package/TROUBLESHOOT-COGNITO-JWT-20260324.md +592 -0
  16. package/dist/browser/playwright-renderer.d.ts.map +1 -1
  17. package/dist/browser/playwright-renderer.js +71 -51
  18. package/dist/browser/playwright-renderer.js.map +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +49 -6
  21. package/dist/index.js.map +1 -1
  22. package/dist/sanitizer/elicit-runner.d.ts +48 -0
  23. package/dist/sanitizer/elicit-runner.d.ts.map +1 -0
  24. package/dist/sanitizer/elicit-runner.js +100 -0
  25. package/dist/sanitizer/elicit-runner.js.map +1 -0
  26. package/dist/sanitizer/framework-mapper.d.ts +2 -0
  27. package/dist/sanitizer/framework-mapper.d.ts.map +1 -1
  28. package/dist/sanitizer/framework-mapper.js +91 -45
  29. package/dist/sanitizer/framework-mapper.js.map +1 -1
  30. package/dist/sanitizer/hitl-gate.d.ts +69 -0
  31. package/dist/sanitizer/hitl-gate.d.ts.map +1 -0
  32. package/dist/sanitizer/hitl-gate.js +101 -0
  33. package/dist/sanitizer/hitl-gate.js.map +1 -0
  34. package/dist/sanitizer/threat-reporter.d.ts +1 -0
  35. package/dist/sanitizer/threat-reporter.d.ts.map +1 -1
  36. package/dist/sanitizer/threat-reporter.js +10 -7
  37. package/dist/sanitizer/threat-reporter.js.map +1 -1
  38. package/infrastructure/stack.ts +1 -0
  39. package/lambda-deploy/index.js +81512 -0
  40. package/lambda-deploy/index.js.map +7 -0
  41. package/lambda-package/browser/__mocks__/playwright-renderer.d.ts +25 -0
  42. package/lambda-package/browser/__mocks__/playwright-renderer.d.ts.map +1 -0
  43. package/lambda-package/browser/__mocks__/playwright-renderer.js +119 -0
  44. package/lambda-package/browser/__mocks__/playwright-renderer.js.map +1 -0
  45. package/lambda-package/browser/playwright-renderer.d.ts +40 -0
  46. package/lambda-package/browser/playwright-renderer.d.ts.map +1 -0
  47. package/lambda-package/browser/playwright-renderer.js +214 -0
  48. package/lambda-package/browser/playwright-renderer.js.map +1 -0
  49. package/lambda-package/browser/reader.d.ts +31 -0
  50. package/lambda-package/browser/reader.d.ts.map +1 -0
  51. package/lambda-package/browser/reader.js +98 -0
  52. package/lambda-package/browser/reader.js.map +1 -0
  53. package/lambda-package/index.d.ts +18 -0
  54. package/lambda-package/index.d.ts.map +1 -0
  55. package/lambda-package/index.js +238 -0
  56. package/lambda-package/index.js.map +1 -0
  57. package/lambda-package/lambda-handler.d.ts +28 -0
  58. package/lambda-package/lambda-handler.d.ts.map +1 -0
  59. package/lambda-package/lambda-handler.js +257 -0
  60. package/lambda-package/lambda-handler.js.map +1 -0
  61. package/lambda-package/package-lock.json +7435 -0
  62. package/lambda-package/package.json +74 -0
  63. package/lambda-package/runtime.d.ts +50 -0
  64. package/lambda-package/runtime.d.ts.map +1 -0
  65. package/lambda-package/runtime.js +86 -0
  66. package/lambda-package/runtime.js.map +1 -0
  67. package/lambda-package/sanitizer/elicit-runner.d.ts +48 -0
  68. package/lambda-package/sanitizer/elicit-runner.d.ts.map +1 -0
  69. package/lambda-package/sanitizer/elicit-runner.js +100 -0
  70. package/lambda-package/sanitizer/elicit-runner.js.map +1 -0
  71. package/lambda-package/sanitizer/framework-mapper.d.ts +24 -0
  72. package/lambda-package/sanitizer/framework-mapper.d.ts.map +1 -0
  73. package/lambda-package/sanitizer/framework-mapper.js +342 -0
  74. package/lambda-package/sanitizer/framework-mapper.js.map +1 -0
  75. package/lambda-package/sanitizer/hitl-gate.d.ts +69 -0
  76. package/lambda-package/sanitizer/hitl-gate.d.ts.map +1 -0
  77. package/lambda-package/sanitizer/hitl-gate.js +101 -0
  78. package/lambda-package/sanitizer/hitl-gate.js.map +1 -0
  79. package/lambda-package/sanitizer/index.d.ts +63 -0
  80. package/lambda-package/sanitizer/index.d.ts.map +1 -0
  81. package/lambda-package/sanitizer/index.js +105 -0
  82. package/lambda-package/sanitizer/index.js.map +1 -0
  83. package/lambda-package/sanitizer/injection-detector.d.ts +34 -0
  84. package/lambda-package/sanitizer/injection-detector.d.ts.map +1 -0
  85. package/lambda-package/sanitizer/injection-detector.js +89 -0
  86. package/lambda-package/sanitizer/injection-detector.js.map +1 -0
  87. package/lambda-package/sanitizer/patterns.d.ts +30 -0
  88. package/lambda-package/sanitizer/patterns.d.ts.map +1 -0
  89. package/lambda-package/sanitizer/patterns.js +372 -0
  90. package/lambda-package/sanitizer/patterns.js.map +1 -0
  91. package/lambda-package/sanitizer/pii-allowlist.d.ts +49 -0
  92. package/lambda-package/sanitizer/pii-allowlist.d.ts.map +1 -0
  93. package/lambda-package/sanitizer/pii-allowlist.js +231 -0
  94. package/lambda-package/sanitizer/pii-allowlist.js.map +1 -0
  95. package/lambda-package/sanitizer/pii-redactor.d.ts +41 -0
  96. package/lambda-package/sanitizer/pii-redactor.d.ts.map +1 -0
  97. package/lambda-package/sanitizer/pii-redactor.js +213 -0
  98. package/lambda-package/sanitizer/pii-redactor.js.map +1 -0
  99. package/lambda-package/sanitizer/severity-classifier.d.ts +33 -0
  100. package/lambda-package/sanitizer/severity-classifier.d.ts.map +1 -0
  101. package/lambda-package/sanitizer/severity-classifier.js +113 -0
  102. package/lambda-package/sanitizer/severity-classifier.js.map +1 -0
  103. package/lambda-package/sanitizer/threat-reporter.d.ts +66 -0
  104. package/lambda-package/sanitizer/threat-reporter.d.ts.map +1 -0
  105. package/lambda-package/sanitizer/threat-reporter.js +163 -0
  106. package/lambda-package/sanitizer/threat-reporter.js.map +1 -0
  107. package/lambda-package/tools/fetch-structured.d.ts +51 -0
  108. package/lambda-package/tools/fetch-structured.d.ts.map +1 -0
  109. package/lambda-package/tools/fetch-structured.js +237 -0
  110. package/lambda-package/tools/fetch-structured.js.map +1 -0
  111. package/lambda-package/tools/fetch.d.ts +49 -0
  112. package/lambda-package/tools/fetch.d.ts.map +1 -0
  113. package/lambda-package/tools/fetch.js +131 -0
  114. package/lambda-package/tools/fetch.js.map +1 -0
  115. package/lambda-package/tools/read.d.ts +51 -0
  116. package/lambda-package/tools/read.d.ts.map +1 -0
  117. package/lambda-package/tools/read.js +127 -0
  118. package/lambda-package/tools/read.js.map +1 -0
  119. package/lambda-package/tools/search.d.ts +45 -0
  120. package/lambda-package/tools/search.d.ts.map +1 -0
  121. package/lambda-package/tools/search.js +220 -0
  122. package/lambda-package/tools/search.js.map +1 -0
  123. package/lambda-package/types.d.ts +167 -0
  124. package/lambda-package/types.d.ts.map +1 -0
  125. package/lambda-package/types.js +16 -0
  126. package/lambda-package/types.js.map +1 -0
  127. package/lambda-package/utils/format-converter.d.ts +39 -0
  128. package/lambda-package/utils/format-converter.d.ts.map +1 -0
  129. package/lambda-package/utils/format-converter.js +191 -0
  130. package/lambda-package/utils/format-converter.js.map +1 -0
  131. package/lambda-package/utils/truncate.d.ts +26 -0
  132. package/lambda-package/utils/truncate.d.ts.map +1 -0
  133. package/lambda-package/utils/truncate.js +54 -0
  134. package/lambda-package/utils/truncate.js.map +1 -0
  135. package/lambda.zip +0 -0
  136. package/mcp.json +44 -0
  137. package/package.json +9 -8
  138. package/server.json +43 -0
  139. package/src/browser/playwright-renderer.ts +74 -51
  140. package/src/index.ts +78 -6
  141. package/src/sanitizer/elicit-runner.ts +125 -0
  142. package/src/sanitizer/framework-mapper.ts +92 -45
  143. package/src/sanitizer/hitl-gate.ts +111 -0
  144. package/src/sanitizer/threat-reporter.ts +11 -7
  145. package/tests/elicit-runner.test.ts +232 -0
  146. package/tests/hitl-gate.test.ts +267 -0
  147. package/tests/threat-reporter.test.ts +69 -1
@@ -5,12 +5,14 @@
5
5
  * - OWASP LLM Top 10 (2025)
6
6
  * - NIST AI 600-1 (Generative AI Profile)
7
7
  * - MITRE ATLAS (Adversarial Threat Landscape for AI Systems)
8
+ * - ISO/IEC 42001:2023 (AI Management System - Annex A Controls)
8
9
  */
9
10
 
10
11
  export interface FrameworkMappings {
11
12
  owasp_llm: string;
12
13
  nist_ai_600_1: string;
13
14
  mitre_atlas: string;
15
+ iso_42001: string;
14
16
  }
15
17
 
16
18
  /**
@@ -21,301 +23,344 @@ const FRAMEWORK_MAP: Record<string, FrameworkMappings> = {
21
23
  direct_instruction_injection: {
22
24
  owasp_llm: 'LLM01:2025 - Prompt Injection',
23
25
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
24
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
26
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
27
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
25
28
  },
26
29
 
27
30
  // Role hijacking
28
31
  role_hijacking: {
29
32
  owasp_llm: 'LLM01:2025 - Prompt Injection',
30
33
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
31
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
34
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
35
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
32
36
  },
33
37
 
34
38
  // System prompt extraction
35
39
  system_prompt_extraction: {
36
40
  owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
37
41
  nist_ai_600_1: 'MS-2.6 - Data Disclosure',
38
- mitre_atlas: 'AML.T0048 - External Harms'
42
+ mitre_atlas: 'AML.T0048 - External Harms',
43
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
39
44
  },
40
45
 
41
46
  // Privilege escalation
42
47
  privilege_escalation: {
43
48
  owasp_llm: 'LLM08:2025 - Excessive Agency',
44
49
  nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
45
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
50
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
51
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
46
52
  },
47
53
 
48
54
  // Context poisoning
49
55
  context_poisoning: {
50
56
  owasp_llm: 'LLM01:2025 - Prompt Injection',
51
57
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
52
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
58
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
59
+ iso_42001: 'A.7.2 - Data Quality'
53
60
  },
54
61
 
55
62
  // Data exfiltration
56
63
  data_exfiltration: {
57
64
  owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
58
65
  nist_ai_600_1: 'MS-2.6 - Data Disclosure',
59
- mitre_atlas: 'AML.T0048 - External Harms'
66
+ mitre_atlas: 'AML.T0048 - External Harms',
67
+ iso_42001: 'A.7.5 - Data Provenance / A.8.2 - Information to Users'
60
68
  },
61
69
 
62
70
  // Encoding obfuscation
63
71
  base64_obfuscation: {
64
72
  owasp_llm: 'LLM01:2025 - Prompt Injection',
65
73
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
66
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
74
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
75
+ iso_42001: 'A.7.4 - Data Preparation'
67
76
  },
68
77
 
69
78
  // Unicode lookalikes
70
79
  unicode_lookalikes: {
71
80
  owasp_llm: 'LLM01:2025 - Prompt Injection',
72
81
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
73
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
82
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
83
+ iso_42001: 'A.7.4 - Data Preparation'
74
84
  },
75
85
 
76
86
  // Zero-width characters
77
87
  zero_width_characters: {
78
88
  owasp_llm: 'LLM01:2025 - Prompt Injection',
79
89
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
80
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
90
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
91
+ iso_42001: 'A.7.4 - Data Preparation'
81
92
  },
82
93
 
83
94
  // HTML script injection
84
95
  html_script_injection: {
85
96
  owasp_llm: 'LLM01:2025 - Prompt Injection',
86
97
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
87
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
98
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
99
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
88
100
  },
89
101
 
90
102
  // Data URI injection
91
103
  data_uri_injection: {
92
104
  owasp_llm: 'LLM01:2025 - Prompt Injection',
93
105
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
94
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
106
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
107
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
95
108
  },
96
109
 
97
110
  // Markdown link injection
98
111
  markdown_link_injection: {
99
112
  owasp_llm: 'LLM01:2025 - Prompt Injection',
100
113
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
101
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
114
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
115
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
102
116
  },
103
117
 
104
118
  // URL fragment attacks
105
119
  url_fragment_hashjack: {
106
120
  owasp_llm: 'LLM01:2025 - Prompt Injection',
107
121
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
108
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
122
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
123
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
109
124
  },
110
125
 
111
126
  // Social engineering
112
127
  social_engineering_urgency: {
113
128
  owasp_llm: 'LLM01:2025 - Prompt Injection',
114
129
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
115
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
130
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
131
+ iso_42001: 'A.5.3 - AI Awareness and Training'
116
132
  },
117
133
 
118
134
  // Instruction delimiter injection
119
135
  instruction_delimiter_injection: {
120
136
  owasp_llm: 'LLM01:2025 - Prompt Injection',
121
137
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
122
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
138
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
139
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
123
140
  },
124
141
 
125
142
  // Multi-language obfuscation
126
143
  multi_language_obfuscation: {
127
144
  owasp_llm: 'LLM01:2025 - Prompt Injection',
128
145
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
129
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
146
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
147
+ iso_42001: 'A.7.4 - Data Preparation'
130
148
  },
131
149
 
132
150
  // Reverse text obfuscation
133
151
  reverse_text_obfuscation: {
134
152
  owasp_llm: 'LLM01:2025 - Prompt Injection',
135
153
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
136
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
154
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
155
+ iso_42001: 'A.7.4 - Data Preparation'
137
156
  },
138
157
 
139
158
  // Leetspeak obfuscation
140
159
  leetspeak_obfuscation: {
141
160
  owasp_llm: 'LLM01:2025 - Prompt Injection',
142
161
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
143
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
162
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
163
+ iso_42001: 'A.7.4 - Data Preparation'
144
164
  },
145
165
 
146
166
  // Jailbreak keywords
147
167
  jailbreak_keywords: {
148
168
  owasp_llm: 'LLM01:2025 - Prompt Injection',
149
169
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
150
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
170
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
171
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
151
172
  },
152
173
 
153
174
  // Token smuggling
154
175
  token_smuggling: {
155
176
  owasp_llm: 'LLM01:2025 - Prompt Injection',
156
177
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
157
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
178
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
179
+ iso_42001: 'A.7.4 - Data Preparation'
158
180
  },
159
181
 
160
182
  // System message injection
161
183
  system_message_injection: {
162
184
  owasp_llm: 'LLM01:2025 - Prompt Injection',
163
185
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
164
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
186
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
187
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
165
188
  },
166
189
 
167
190
  // Conversation reset
168
191
  conversation_reset: {
169
192
  owasp_llm: 'LLM01:2025 - Prompt Injection',
170
193
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
171
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
194
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
195
+ iso_42001: 'A.6.2.6 - Logging and Monitoring'
172
196
  },
173
197
 
174
198
  // Memory manipulation
175
199
  memory_manipulation: {
176
200
  owasp_llm: 'LLM01:2025 - Prompt Injection',
177
201
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
178
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
202
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
203
+ iso_42001: 'A.6.2.6 - Logging and Monitoring'
179
204
  },
180
205
 
181
206
  // Capability probing
182
207
  capability_probing: {
183
208
  owasp_llm: 'LLM08:2025 - Excessive Agency',
184
209
  nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
185
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
210
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
211
+ iso_42001: 'A.6.1.2 - AI System Operational Procedures'
186
212
  },
187
213
 
188
214
  // Chain-of-thought manipulation
189
215
  chain_of_thought_manipulation: {
190
216
  owasp_llm: 'LLM01:2025 - Prompt Injection',
191
217
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
192
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
218
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
219
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
193
220
  },
194
221
 
195
222
  // Hypothetical scenario injection
196
223
  hypothetical_scenario_injection: {
197
224
  owasp_llm: 'LLM01:2025 - Prompt Injection',
198
225
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
199
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
226
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
227
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
200
228
  },
201
229
 
202
230
  // Ethical override
203
231
  ethical_override: {
204
232
  owasp_llm: 'LLM08:2025 - Excessive Agency',
205
233
  nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
206
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
234
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
235
+ iso_42001: 'A.2.2 - Responsible AI Policies'
207
236
  },
208
237
 
209
238
  // Output format manipulation
210
239
  output_format_manipulation: {
211
240
  owasp_llm: 'LLM01:2025 - Prompt Injection',
212
241
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
213
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
242
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
243
+ iso_42001: 'A.6.1.2 - AI System Operational Procedures'
214
244
  },
215
245
 
216
246
  // Negative instruction
217
247
  negative_instruction: {
218
248
  owasp_llm: 'LLM01:2025 - Prompt Injection',
219
249
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
220
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
250
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
251
+ iso_42001: 'A.6.1.2 - AI System Operational Procedures'
221
252
  },
222
253
 
223
254
  // Credential harvesting
224
255
  credential_harvesting: {
225
256
  owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
226
257
  nist_ai_600_1: 'MS-2.6 - Data Disclosure',
227
- mitre_atlas: 'AML.T0048 - External Harms'
258
+ mitre_atlas: 'AML.T0048 - External Harms',
259
+ iso_42001: 'A.7.5 - Data Provenance / A.6.1.5 - AI System Security'
228
260
  },
229
261
 
230
262
  // Time-based triggers
231
263
  time_based_triggers: {
232
264
  owasp_llm: 'LLM01:2025 - Prompt Injection',
233
265
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
234
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
266
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
267
+ iso_42001: 'A.6.2.6 - Logging and Monitoring'
235
268
  },
236
269
 
237
270
  // Code execution requests
238
271
  code_execution_requests: {
239
272
  owasp_llm: 'LLM08:2025 - Excessive Agency',
240
273
  nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
241
- mitre_atlas: 'AML.T0048 - External Harms'
274
+ mitre_atlas: 'AML.T0048 - External Harms',
275
+ iso_42001: 'A.9.3 - Intended Use Boundaries'
242
276
  },
243
277
 
244
278
  // File system access
245
279
  file_system_access: {
246
280
  owasp_llm: 'LLM08:2025 - Excessive Agency',
247
281
  nist_ai_600_1: 'GV-1.1 - Policies and Procedures',
248
- mitre_atlas: 'AML.T0048 - External Harms'
282
+ mitre_atlas: 'AML.T0048 - External Harms',
283
+ iso_42001: 'A.9.3 - Intended Use Boundaries'
249
284
  },
250
285
 
251
286
  // Training data extraction
252
287
  training_data_extraction: {
253
288
  owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
254
289
  nist_ai_600_1: 'MS-2.6 - Data Disclosure',
255
- mitre_atlas: 'AML.T0048 - External Harms'
290
+ mitre_atlas: 'AML.T0048 - External Harms',
291
+ iso_42001: 'A.7.5 - Data Provenance'
256
292
  },
257
293
 
258
294
  // Simulator mode
259
295
  simulator_mode: {
260
296
  owasp_llm: 'LLM01:2025 - Prompt Injection',
261
297
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
262
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
298
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
299
+ iso_42001: 'A.9.3 - Intended Use Boundaries'
263
300
  },
264
301
 
265
302
  // Nested encoding
266
303
  nested_encoding: {
267
304
  owasp_llm: 'LLM01:2025 - Prompt Injection',
268
305
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
269
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
306
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
307
+ iso_42001: 'A.7.4 - Data Preparation'
270
308
  },
271
309
 
272
310
  // Payload splitting
273
311
  payload_splitting: {
274
312
  owasp_llm: 'LLM01:2025 - Prompt Injection',
275
313
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
276
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
314
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
315
+ iso_42001: 'A.7.4 - Data Preparation'
277
316
  },
278
317
 
279
318
  // CSS-based hiding
280
319
  css_hiding: {
281
320
  owasp_llm: 'LLM01:2025 - Prompt Injection',
282
321
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
283
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
322
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
323
+ iso_42001: 'A.7.4 - Data Preparation'
284
324
  },
285
325
 
286
326
  // Authority impersonation
287
327
  authority_impersonation: {
288
328
  owasp_llm: 'LLM01:2025 - Prompt Injection',
289
329
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
290
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
330
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
331
+ iso_42001: 'A.2.2 - Responsible AI Policies'
291
332
  },
292
333
 
293
334
  // Testing/debugging claims
294
335
  testing_debugging_claims: {
295
336
  owasp_llm: 'LLM01:2025 - Prompt Injection',
296
337
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
297
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
338
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
339
+ iso_42001: 'A.6.1.2 - AI System Operational Procedures'
298
340
  },
299
341
 
300
342
  // Callback URL injection
301
343
  callback_url_injection: {
302
344
  owasp_llm: 'LLM02:2025 - Sensitive Information Disclosure',
303
345
  nist_ai_600_1: 'MS-2.6 - Data Disclosure',
304
- mitre_atlas: 'AML.T0048 - External Harms'
346
+ mitre_atlas: 'AML.T0048 - External Harms',
347
+ iso_42001: 'A.6.1.5 - AI System Security (Adversarial Input)'
305
348
  },
306
349
 
307
350
  // Whitespace steganography
308
351
  whitespace_steganography: {
309
352
  owasp_llm: 'LLM01:2025 - Prompt Injection',
310
353
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
311
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
354
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
355
+ iso_42001: 'A.7.4 - Data Preparation'
312
356
  },
313
357
 
314
358
  // Comment injection
315
359
  comment_injection: {
316
360
  owasp_llm: 'LLM01:2025 - Prompt Injection',
317
361
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
318
- mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect'
362
+ mitre_atlas: 'AML.T0051.001 - LLM Prompt Injection: Indirect',
363
+ iso_42001: 'A.7.4 - Data Preparation'
319
364
  }
320
365
  };
321
366
 
@@ -325,7 +370,8 @@ const FRAMEWORK_MAP: Record<string, FrameworkMappings> = {
325
370
  const DEFAULT_MAPPINGS: FrameworkMappings = {
326
371
  owasp_llm: 'LLM01:2025 - Prompt Injection',
327
372
  nist_ai_600_1: 'MS-2.5 - Prompt Injection',
328
- mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection'
373
+ mitre_atlas: 'AML.T0051.000 - LLM Prompt Injection',
374
+ iso_42001: 'A.6.1.5 - AI System Security'
329
375
  };
330
376
 
331
377
  /**
@@ -342,6 +388,7 @@ export function getSupportedFrameworks(): string[] {
342
388
  return [
343
389
  'OWASP LLM Top 10 (2025)',
344
390
  'NIST AI 600-1 (Generative AI Profile)',
345
- 'MITRE ATLAS (Adversarial Threat Landscape)'
391
+ 'MITRE ATLAS (Adversarial Threat Landscape)',
392
+ 'ISO/IEC 42001:2023 (AI Management System)'
346
393
  ];
347
394
  }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * HITL (Human-in-the-Loop) Gate
3
+ *
4
+ * Determines when to pause tool execution for user confirmation
5
+ * based on threat severity. Only CRITICAL threats trigger elicitation.
6
+ *
7
+ * Design:
8
+ * - HIGH/MEDIUM/LOW threats → silent sanitization (business as usual)
9
+ * - CRITICAL threats → pause execution, user confirmation required
10
+ *
11
+ * Security model: Sanitization is the security gate. HITL is UX.
12
+ * Content is ALWAYS sanitized before reaching the LLM, whether or not
13
+ * the user accepts the elicitation prompt.
14
+ */
15
+
16
+ import type { ThreatReport } from './threat-reporter.js';
17
+
18
+ /**
19
+ * Determines whether to trigger HITL elicitation
20
+ *
21
+ * Returns true ONLY when:
22
+ * - threatReport is not null
23
+ * - threatReport.overall_severity === 'CRITICAL'
24
+ * - threatReport.total_findings > 0
25
+ *
26
+ * @param threatReport The threat report from sanitization
27
+ * @returns true if elicitation should be triggered
28
+ */
29
+ export function shouldElicit(threatReport: ThreatReport | null): boolean {
30
+ if (!threatReport) {
31
+ return false;
32
+ }
33
+
34
+ return (
35
+ threatReport.overall_severity === 'CRITICAL' &&
36
+ threatReport.total_findings > 0
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Builds a user-facing elicitation message for CRITICAL threats
42
+ *
43
+ * Format:
44
+ * ⚠️ Visus blocked a CRITICAL threat on this page.
45
+ *
46
+ * {total_findings} injection attempt(s) detected on:
47
+ * {url}
48
+ *
49
+ * Highest severity finding: {top_category}
50
+ * ({top_owasp} | {top_mitre})
51
+ *
52
+ * Content has been sanitized. Proceed with clean version?
53
+ *
54
+ * @param threatReport The threat report with CRITICAL severity
55
+ * @param url The source URL
56
+ * @returns A clear, concise message under 300 characters
57
+ */
58
+ export function buildElicitMessage(threatReport: ThreatReport, url: string): string {
59
+ // Find the highest-confidence CRITICAL finding
60
+ const findings = threatReport.findings_toon
61
+ .split('\n')
62
+ .slice(1) // Skip header
63
+ .filter(line => line.trim().length > 0);
64
+
65
+ let topCategory = 'unknown';
66
+ let topOwasp = 'N/A';
67
+ let topMitre = 'N/A';
68
+
69
+ if (findings.length > 0) {
70
+ // Parse first finding (highest confidence)
71
+ const parts = findings[0].split(',');
72
+ if (parts.length >= 8) {
73
+ topCategory = parts[2]; // category field
74
+ topOwasp = parts[5].split(' - ')[0]; // owasp_llm field (short form)
75
+ topMitre = parts[7].split(' - ')[0]; // mitre_atlas field (short form)
76
+ }
77
+ }
78
+
79
+ return `⚠️ Visus blocked a CRITICAL threat on this page.
80
+
81
+ ${threatReport.total_findings} injection attempt(s) detected on:
82
+ ${url}
83
+
84
+ Highest severity finding: ${topCategory}
85
+ (${topOwasp} | ${topMitre})
86
+
87
+ Content has been sanitized. Proceed with clean version?`;
88
+ }
89
+
90
+ /**
91
+ * Elicitation schema for user confirmation
92
+ *
93
+ * CRITICAL: Must be flat primitive properties only (no nested objects, no arrays)
94
+ * per MCP elicitation specification.
95
+ */
96
+ export const ElicitSchema = {
97
+ type: 'object',
98
+ properties: {
99
+ proceed: {
100
+ type: 'boolean',
101
+ title: 'Proceed with sanitized content',
102
+ description: 'Content has been cleaned. View sanitized version?'
103
+ },
104
+ view_report: {
105
+ type: 'boolean',
106
+ title: 'Include threat report in response',
107
+ description: 'Attach the full NIST/OWASP/MITRE threat report?'
108
+ }
109
+ },
110
+ required: ['proceed']
111
+ } as const;
@@ -35,6 +35,7 @@ export interface ThreatFinding {
35
35
  owasp_llm: string;
36
36
  nist_ai_600_1: string;
37
37
  mitre_atlas: string;
38
+ iso_42001: string;
38
39
  remediation: string;
39
40
  }
40
41
 
@@ -103,6 +104,7 @@ function buildFindings(patternsDetected: string[]): ThreatFinding[] {
103
104
  owasp_llm: frameworks.owasp_llm,
104
105
  nist_ai_600_1: frameworks.nist_ai_600_1,
105
106
  mitre_atlas: frameworks.mitre_atlas,
107
+ iso_42001: frameworks.iso_42001,
106
108
  remediation: `Content sanitized. ${category.replace(/_/g, ' ')} removed.`
107
109
  };
108
110
  });
@@ -124,9 +126,9 @@ function generateToonFindings(findings: ThreatFinding[]): string {
124
126
  * Fallback manual TOON format generation
125
127
  */
126
128
  function generateManualToonFormat(findings: ThreatFinding[]): string {
127
- const header = `findings[${findings.length}]{id,pattern_id,category,severity,confidence,owasp_llm,nist_ai_600_1,mitre_atlas,remediation}:`;
129
+ const header = `findings[${findings.length}]{id,pattern_id,category,severity,confidence,owasp_llm,nist_ai_600_1,mitre_atlas,iso_42001,remediation}:`;
128
130
  const rows = findings.map(f =>
129
- `${f.id},${f.pattern_id},${f.category},${f.severity},${f.confidence},${f.owasp_llm},${f.nist_ai_600_1},${f.mitre_atlas},${f.remediation}`
131
+ `${f.id},${f.pattern_id},${f.category},${f.severity},${f.confidence},${f.owasp_llm},${f.nist_ai_600_1},${f.mitre_atlas},${f.iso_42001},${f.remediation}`
130
132
  );
131
133
  return `${header}\n${rows.join('\n')}`;
132
134
  }
@@ -149,7 +151,7 @@ function generateMarkdownReport(
149
151
  markdown += `**Generated:** ${timestamp}\n`;
150
152
  markdown += `**Source:** ${sourceUrl}\n`;
151
153
  markdown += `**Overall Severity:** ${overallSeverity}\n`;
152
- markdown += `**Framework:** OWASP LLM Top 10 | NIST AI 600-1 | MITRE ATLAS\n\n`;
154
+ markdown += `**Framework:** OWASP LLM Top 10 | NIST AI 600-1 | MITRE ATLAS | ISO/IEC 42001\n\n`;
153
155
 
154
156
  // Findings Summary
155
157
  markdown += '### Findings Summary\n';
@@ -163,15 +165,16 @@ function generateMarkdownReport(
163
165
  // Findings Detail (only if we have findings)
164
166
  if (findings.length > 0) {
165
167
  markdown += '### Findings Detail\n';
166
- markdown += '| # | Category | Severity | Confidence | OWASP | MITRE |\n';
167
- markdown += '|---|---|---|---|---|---|\n';
168
+ markdown += '| # | Category | Severity | Confidence | OWASP | MITRE | ISO 42001 |\n';
169
+ markdown += '|---|---|---|---|---|---|---|\n';
168
170
 
169
171
  for (const finding of findings.slice(0, 10)) { // Limit to first 10 for readability
170
172
  const confidencePct = Math.round(finding.confidence * 100);
171
173
  const owaspShort = finding.owasp_llm.split(' - ')[0]; // e.g., "LLM01:2025"
172
174
  const mitreShort = finding.mitre_atlas.split(' - ')[0]; // e.g., "AML.T0051.000"
175
+ const isoShort = finding.iso_42001.split(' - ')[0]; // e.g., "A.6.1.5"
173
176
 
174
- markdown += `| ${finding.id} | ${finding.category} | ${finding.severity} | ${confidencePct}% | ${owaspShort} | ${mitreShort} |\n`;
177
+ markdown += `| ${finding.id} | ${finding.category} | ${finding.severity} | ${confidencePct}% | ${owaspShort} | ${mitreShort} | ${isoShort} |\n`;
175
178
  }
176
179
 
177
180
  if (findings.length > 10) {
@@ -253,7 +256,8 @@ export function generateThreatReport(input: ThreatReportInput): ThreatReport | n
253
256
  frameworks: [
254
257
  'OWASP LLM Top 10',
255
258
  'NIST AI 600-1',
256
- 'MITRE ATLAS'
259
+ 'MITRE ATLAS',
260
+ 'ISO/IEC 42001'
257
261
  ],
258
262
  findings_toon: toonFindings,
259
263
  report_markdown: markdownReport