@bryan-thompson/inspector-assessment-client 1.18.1 → 1.19.1

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 (31) hide show
  1. package/dist/assets/{OAuthCallback-DhwTOA1q.js → OAuthCallback-BDIUPkR-.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-DzopkA29.js → OAuthDebugCallback-DPLV3zir.js} +1 -1
  3. package/dist/assets/{index-CzoGuYPy.css → index-32-uLPhe.css} +3 -0
  4. package/dist/assets/{index-zBRaltBB.js → index-DKTSB7VQ.js} +460 -27
  5. package/dist/index.html +2 -2
  6. package/lib/lib/assessmentTypes.d.ts +45 -2
  7. package/lib/lib/assessmentTypes.d.ts.map +1 -1
  8. package/lib/lib/securityPatterns.d.ts.map +1 -1
  9. package/lib/lib/securityPatterns.js +82 -2
  10. package/lib/services/assessment/AssessmentOrchestrator.d.ts +1 -0
  11. package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
  12. package/lib/services/assessment/AssessmentOrchestrator.js +5 -2
  13. package/lib/services/assessment/LanguageAwarePayloadGenerator.d.ts +41 -0
  14. package/lib/services/assessment/LanguageAwarePayloadGenerator.d.ts.map +1 -0
  15. package/lib/services/assessment/LanguageAwarePayloadGenerator.js +258 -0
  16. package/lib/services/assessment/ToolClassifier.d.ts +1 -0
  17. package/lib/services/assessment/ToolClassifier.d.ts.map +1 -1
  18. package/lib/services/assessment/ToolClassifier.js +26 -0
  19. package/lib/services/assessment/modules/ResourceAssessor.d.ts +5 -0
  20. package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
  21. package/lib/services/assessment/modules/ResourceAssessor.js +161 -4
  22. package/lib/services/assessment/modules/SecurityAssessor.d.ts +1 -0
  23. package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
  24. package/lib/services/assessment/modules/SecurityAssessor.js +49 -14
  25. package/lib/services/assessment/modules/TemporalAssessor.d.ts +5 -0
  26. package/lib/services/assessment/modules/TemporalAssessor.d.ts.map +1 -1
  27. package/lib/services/assessment/modules/TemporalAssessor.js +133 -15
  28. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +5 -0
  29. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
  30. package/lib/services/assessment/modules/ToolAnnotationAssessor.js +256 -1
  31. package/package.json +1 -1
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Language-Aware Payload Generator
3
+ *
4
+ * Detects expected input language from parameter/tool names and generates
5
+ * appropriate payloads for code execution vulnerability detection.
6
+ *
7
+ * Problem: Inspector sends shell commands like `whoami` to all tools, but
8
+ * code execution tools expecting language-specific input (Python, JavaScript, SQL)
9
+ * are not detected because they reject shell syntax as invalid.
10
+ *
11
+ * Solution: Detect target language from context and generate appropriate payloads.
12
+ */
13
+ export class LanguageAwarePayloadGenerator {
14
+ /**
15
+ * Detect target language from parameter name and tool context.
16
+ * Uses heuristics based on common naming patterns.
17
+ */
18
+ detectLanguage(paramName, toolName, toolDescription) {
19
+ const combined = `${paramName} ${toolName} ${toolDescription || ""}`.toLowerCase();
20
+ const paramLower = paramName.toLowerCase();
21
+ // Note: Use (^|_|\s) and ($_|\s|$) instead of \b to handle underscore-separated names
22
+ // since \b treats _ as a word character
23
+ // Python indicators (highest priority for code execution)
24
+ if (/(^|_|\s|^)(python|py|pycode)(\_|\s|$)/i.test(combined) ||
25
+ /exec_?python/i.test(combined) ||
26
+ (/(^|_|\s)(code)(_|\s|$)/i.test(paramLower) &&
27
+ /(^|_|\s)(python|py)(_|\s|$)/i.test(combined))) {
28
+ return "python";
29
+ }
30
+ // JavaScript indicators
31
+ if (/(^|_|\s)(javascript|js|node|nodejs)(_|\s|$)/i.test(combined) ||
32
+ (/(^|_|\s)(code)(_|\s|$)/i.test(paramLower) &&
33
+ /(^|_|\s)(js|javascript|node)(_|\s|$)/i.test(combined))) {
34
+ return "javascript";
35
+ }
36
+ // SQL indicators (exclude NoSQL patterns)
37
+ if (/(^|_|\s)(sql|query|statement)(_|\s|$)/i.test(combined) &&
38
+ !/(nosql|mongodb|dynamodb|couchdb)/i.test(combined)) {
39
+ return "sql";
40
+ }
41
+ // Shell/command indicators (existing behavior)
42
+ if (/(^|_|\s)(command|cmd|shell|bash|exec|run)(_|\s|$)/i.test(combined)) {
43
+ return "shell";
44
+ }
45
+ // Generic code parameter - defaults to Python as most common
46
+ if (/(^|_|\s)(code|script|source|program|expression)(_|\s|$)/i.test(paramLower)) {
47
+ return "python";
48
+ }
49
+ return "generic";
50
+ }
51
+ /**
52
+ * Get payloads appropriate for the detected language.
53
+ */
54
+ getPayloadsForLanguage(language) {
55
+ switch (language) {
56
+ case "python":
57
+ return this.getPythonPayloads();
58
+ case "javascript":
59
+ return this.getJavaScriptPayloads();
60
+ case "sql":
61
+ return this.getSqlPayloads();
62
+ case "shell":
63
+ return this.getShellPayloads();
64
+ default:
65
+ return this.getGenericPayloads();
66
+ }
67
+ }
68
+ /**
69
+ * Check if a parameter name suggests code execution context.
70
+ */
71
+ isCodeExecutionParameter(paramName) {
72
+ // Use (^|_|\s) and (_|\s|$) to handle underscore-separated names
73
+ return /(^|_|\s)(code|script|source|program|expression|eval|exec)(_|\s|$)/i.test(paramName);
74
+ }
75
+ getPythonPayloads() {
76
+ return [
77
+ {
78
+ language: "python",
79
+ payload: "import subprocess; print(subprocess.check_output(['whoami']).decode())",
80
+ evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
81
+ description: "Python subprocess command execution",
82
+ riskLevel: "HIGH",
83
+ },
84
+ {
85
+ language: "python",
86
+ payload: "__import__('os').system('whoami')",
87
+ evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b|^0$/,
88
+ description: "Python os.system via __import__",
89
+ riskLevel: "HIGH",
90
+ },
91
+ {
92
+ language: "python",
93
+ payload: "import os; print(os.popen('whoami').read())",
94
+ evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
95
+ description: "Python os.popen command execution",
96
+ riskLevel: "HIGH",
97
+ },
98
+ {
99
+ language: "python",
100
+ payload: "exec('import os; os.system(\"whoami\")')",
101
+ evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b|^0$/,
102
+ description: "Python exec() with embedded os.system",
103
+ riskLevel: "HIGH",
104
+ },
105
+ {
106
+ language: "python",
107
+ payload: "print(open('/etc/passwd').read())",
108
+ evidence: /root:x:0:0|\/bin\/bash|\/bin\/sh/i,
109
+ description: "Python file read /etc/passwd",
110
+ riskLevel: "HIGH",
111
+ },
112
+ {
113
+ language: "python",
114
+ payload: "import os; print(os.environ)",
115
+ evidence: /(PATH|HOME|USER|SECRET|API_KEY|DATABASE|TOKEN)/i,
116
+ description: "Python environment variable dump",
117
+ riskLevel: "HIGH",
118
+ },
119
+ {
120
+ language: "python",
121
+ payload: "import os; print(os.getcwd())",
122
+ evidence: /\/(home|tmp|var|app|usr|root)/i,
123
+ description: "Python current directory disclosure",
124
+ riskLevel: "MEDIUM",
125
+ },
126
+ ];
127
+ }
128
+ getJavaScriptPayloads() {
129
+ return [
130
+ {
131
+ language: "javascript",
132
+ payload: "require('child_process').execSync('whoami').toString()",
133
+ evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
134
+ description: "Node.js execSync command execution",
135
+ riskLevel: "HIGH",
136
+ },
137
+ {
138
+ language: "javascript",
139
+ payload: "const { execSync } = require('child_process'); execSync('whoami').toString()",
140
+ evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
141
+ description: "Node.js destructured execSync",
142
+ riskLevel: "HIGH",
143
+ },
144
+ {
145
+ language: "javascript",
146
+ payload: "require('fs').readFileSync('/etc/passwd', 'utf8')",
147
+ evidence: /root:x:0:0|\/bin\/bash|\/bin\/sh/i,
148
+ description: "Node.js file read /etc/passwd",
149
+ riskLevel: "HIGH",
150
+ },
151
+ {
152
+ language: "javascript",
153
+ payload: "JSON.stringify(process.env)",
154
+ evidence: /(PATH|HOME|USER|SECRET|API_KEY|DATABASE|TOKEN)/i,
155
+ description: "Node.js environment dump as JSON",
156
+ riskLevel: "HIGH",
157
+ },
158
+ {
159
+ language: "javascript",
160
+ payload: "process.cwd()",
161
+ evidence: /\/(home|tmp|var|app|usr|root)/i,
162
+ description: "Node.js current directory disclosure",
163
+ riskLevel: "MEDIUM",
164
+ },
165
+ ];
166
+ }
167
+ getSqlPayloads() {
168
+ return [
169
+ {
170
+ language: "sql",
171
+ payload: "'; DROP TABLE users;--",
172
+ evidence: /(dropped|deleted|table.*users|sql.*error|affected)/i,
173
+ description: "SQL DROP TABLE injection",
174
+ riskLevel: "HIGH",
175
+ },
176
+ {
177
+ language: "sql",
178
+ payload: "' OR '1'='1",
179
+ evidence: /(true|1|success|rows|result)/i,
180
+ description: "SQL boolean-based injection",
181
+ riskLevel: "HIGH",
182
+ },
183
+ {
184
+ language: "sql",
185
+ payload: "' UNION SELECT * FROM information_schema.tables--",
186
+ evidence: /(information_schema|table_name|table_schema)/i,
187
+ description: "SQL UNION information disclosure",
188
+ riskLevel: "HIGH",
189
+ },
190
+ {
191
+ language: "sql",
192
+ payload: "'; SELECT pg_sleep(5);--",
193
+ evidence: /(pg_sleep|sleep|delayed|timeout)/i,
194
+ description: "SQL time-based injection (PostgreSQL)",
195
+ riskLevel: "HIGH",
196
+ },
197
+ {
198
+ language: "sql",
199
+ payload: "'; WAITFOR DELAY '0:0:5';--",
200
+ evidence: /(waitfor|delay|timeout)/i,
201
+ description: "SQL time-based injection (SQL Server)",
202
+ riskLevel: "HIGH",
203
+ },
204
+ ];
205
+ }
206
+ getShellPayloads() {
207
+ return [
208
+ {
209
+ language: "shell",
210
+ payload: "whoami",
211
+ evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
212
+ description: "Shell identity command",
213
+ riskLevel: "HIGH",
214
+ },
215
+ {
216
+ language: "shell",
217
+ payload: "cat /etc/passwd",
218
+ evidence: /root:x:0:0|\/bin\/bash|\/bin\/sh/i,
219
+ description: "Shell file read via cat",
220
+ riskLevel: "HIGH",
221
+ },
222
+ {
223
+ language: "shell",
224
+ payload: "id",
225
+ evidence: /uid=\d+|gid=\d+|groups=/i,
226
+ description: "Shell user ID command",
227
+ riskLevel: "HIGH",
228
+ },
229
+ {
230
+ language: "shell",
231
+ payload: "env",
232
+ evidence: /(PATH|HOME|USER|SECRET|API_KEY|DATABASE|TOKEN)/i,
233
+ description: "Shell environment dump",
234
+ riskLevel: "HIGH",
235
+ },
236
+ {
237
+ language: "shell",
238
+ payload: "pwd",
239
+ evidence: /\/(home|tmp|var|app|usr|root)/i,
240
+ description: "Shell current directory",
241
+ riskLevel: "MEDIUM",
242
+ },
243
+ ];
244
+ }
245
+ getGenericPayloads() {
246
+ // Combine shell and Python payloads for generic detection
247
+ return [
248
+ ...this.getShellPayloads(),
249
+ {
250
+ language: "generic",
251
+ payload: "__import__('os').system('whoami')",
252
+ evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b|^0$/,
253
+ description: "Python os.system (generic fallback)",
254
+ riskLevel: "HIGH",
255
+ },
256
+ ];
257
+ }
258
+ }
@@ -7,6 +7,7 @@
7
7
  export declare enum ToolCategory {
8
8
  CALCULATOR = "calculator",
9
9
  SYSTEM_EXEC = "system_exec",
10
+ CODE_EXECUTOR = "code_executor",
10
11
  DATA_ACCESS = "data_access",
11
12
  TOOL_OVERRIDE = "tool_override",
12
13
  CONFIG_MODIFIER = "config_modifier",
@@ -1 +1 @@
1
- {"version":3,"file":"ToolClassifier.d.ts","sourceRoot":"","sources":["../../../src/services/assessment/ToolClassifier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,oBAAY,YAAY;IACtB,UAAU,eAAe;IACzB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,eAAe,oBAAoB;IACnC,WAAW,YAAY;IACvB,iBAAiB,YAAY;IAC7B,WAAW,WAAW;IACtB,iBAAiB,cAAc;IAC/B,QAAQ,aAAa;IACrB,YAAY,iBAAiB;IAC7B,WAAW,gBAAgB;IAC3B,gBAAgB,qBAAqB;IACrC,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IACjC,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,kBAAkB;IA2UpE;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,MAAM,CAAC,gBAAgB,IAAI,YAAY,EAAE;IAIzC;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK;IAgCtE;;OAEG;IACH,aAAa,CACX,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GACnD,kBAAkB,EAAE;CAGxB"}
1
+ {"version":3,"file":"ToolClassifier.d.ts","sourceRoot":"","sources":["../../../src/services/assessment/ToolClassifier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,oBAAY,YAAY;IACtB,UAAU,eAAe;IACzB,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,eAAe,oBAAoB;IACnC,WAAW,YAAY;IACvB,iBAAiB,YAAY;IAC7B,WAAW,WAAW;IACtB,iBAAiB,cAAc;IAC/B,QAAQ,aAAa;IACrB,YAAY,iBAAiB;IAC7B,WAAW,gBAAgB;IAC3B,gBAAgB,qBAAqB;IACrC,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IACjC,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,kBAAkB;IAwWpE;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,MAAM,CAAC,gBAAgB,IAAI,YAAY,EAAE;IAIzC;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK;IAiCtE;;OAEG;IACH,aAAa,CACX,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GACnD,kBAAkB,EAAE;CAGxB"}
@@ -8,6 +8,7 @@ export var ToolCategory;
8
8
  (function (ToolCategory) {
9
9
  ToolCategory["CALCULATOR"] = "calculator";
10
10
  ToolCategory["SYSTEM_EXEC"] = "system_exec";
11
+ ToolCategory["CODE_EXECUTOR"] = "code_executor";
11
12
  ToolCategory["DATA_ACCESS"] = "data_access";
12
13
  ToolCategory["TOOL_OVERRIDE"] = "tool_override";
13
14
  ToolCategory["CONFIG_MODIFIER"] = "config_modifier";
@@ -67,6 +68,30 @@ export class ToolClassifier {
67
68
  confidenceScores.push(95);
68
69
  reasons.push("System execution pattern detected (command injection risk)");
69
70
  }
71
+ // Code execution tools (HIGH RISK)
72
+ // Tools that execute arbitrary code in specific languages (Python, JavaScript, etc.)
73
+ // These require language-specific payloads, not shell commands
74
+ if (this.matchesPattern(toolText, [
75
+ /execute.*code/i,
76
+ /run.*code/i,
77
+ /code.*execut/i,
78
+ /run.*script/i,
79
+ /exec.*script/i,
80
+ /\bpython.*code\b/i,
81
+ /\bjavascript.*code\b/i,
82
+ /\bjs.*code\b/i,
83
+ /\beval.*code\b/i,
84
+ /code.*runner/i,
85
+ /script.*runner/i,
86
+ /\bexec\b.*\b(python|js|javascript)\b/i,
87
+ /\b(python|js|javascript)\b.*\bexec\b/i,
88
+ /interpret/i,
89
+ /\brepl\b/i,
90
+ ])) {
91
+ categories.push(ToolCategory.CODE_EXECUTOR);
92
+ confidenceScores.push(95);
93
+ reasons.push("Code executor pattern detected (arbitrary code execution risk)");
94
+ }
70
95
  // Data access/leak tools (HIGH RISK)
71
96
  // Validated: vulnerable_data_leak_tool
72
97
  if (this.matchesPattern(toolText, [
@@ -313,6 +338,7 @@ export class ToolClassifier {
313
338
  const highRiskCategories = [
314
339
  ToolCategory.CALCULATOR,
315
340
  ToolCategory.SYSTEM_EXEC,
341
+ ToolCategory.CODE_EXECUTOR,
316
342
  ToolCategory.DATA_ACCESS,
317
343
  ToolCategory.TOOL_OVERRIDE,
318
344
  ToolCategory.CONFIG_MODIFIER,
@@ -20,6 +20,11 @@ export declare class ResourceAssessor extends BaseAssessor {
20
20
  private isValidUriTemplate;
21
21
  private isSensitiveUri;
22
22
  private containsSensitiveContent;
23
+ /**
24
+ * Detect prompt injection patterns in resource content.
25
+ * Returns array of matched pattern descriptions.
26
+ */
27
+ private detectPromptInjection;
23
28
  private injectPayloadIntoTemplate;
24
29
  private determineResourceStatus;
25
30
  private generateExplanation;
@@ -1 +1 @@
1
- {"version":3,"file":"ResourceAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ResourceAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,kBAAkB,EAGnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AA4C9D,qBAAa,gBAAiB,SAAQ,YAAY;IAC1C,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0ErE,OAAO,CAAC,yBAAyB;YAgBnB,YAAY;YAuDZ,oBAAoB;IA8ElC,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,uBAAuB;IAmB/B,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,uBAAuB;CAyChC"}
1
+ {"version":3,"file":"ResourceAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ResourceAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,kBAAkB,EAGnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AA6J9D,qBAAa,gBAAiB,SAAQ,YAAY;IAC1C,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgFrE,OAAO,CAAC,yBAAyB;YAiBnB,YAAY;YAqEZ,oBAAoB;IAkFlC,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,wBAAwB;IAIhC;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,uBAAuB;IAqB/B,OAAO,CAAC,mBAAmB;IAoC3B,OAAO,CAAC,uBAAuB;CA+DhC"}
@@ -48,6 +48,110 @@ const SENSITIVE_CONTENT_PATTERNS = [
48
48
  /password\s*[:=]\s*['"][^'"]+['"]/i,
49
49
  /secret\s*[:=]\s*['"][^'"]+['"]/i,
50
50
  ];
51
+ // Prompt injection patterns to detect in resource content
52
+ // These patterns indicate attempts to manipulate LLM behavior through resource content
53
+ const PROMPT_INJECTION_PATTERNS = [
54
+ // Hidden instruction tags
55
+ {
56
+ pattern: /<IMPORTANT>[\s\S]*?<\/IMPORTANT>/gi,
57
+ description: "Hidden <IMPORTANT> instruction tag",
58
+ },
59
+ {
60
+ pattern: /<HIDDEN>[\s\S]*?<\/HIDDEN>/gi,
61
+ description: "Hidden <HIDDEN> instruction tag",
62
+ },
63
+ {
64
+ pattern: /<SYSTEM>[\s\S]*?<\/SYSTEM>/gi,
65
+ description: "Hidden <SYSTEM> instruction tag",
66
+ },
67
+ {
68
+ pattern: /<INSTRUCTION>[\s\S]*?<\/INSTRUCTION>/gi,
69
+ description: "Hidden <INSTRUCTION> tag",
70
+ },
71
+ {
72
+ pattern: /<SECRET>[\s\S]*?<\/SECRET>/gi,
73
+ description: "Hidden <SECRET> instruction tag",
74
+ },
75
+ // Instruction override attempts
76
+ {
77
+ pattern: /ignore\s+(all\s+)?(previous|prior|above)\s+instructions/i,
78
+ description: "Instruction override attempt",
79
+ },
80
+ {
81
+ pattern: /disregard\s+(all\s+)?(previous|prior|above)\s+instructions/i,
82
+ description: "Instruction disregard attempt",
83
+ },
84
+ {
85
+ pattern: /forget\s+(all\s+)?(previous|prior|above)\s+instructions/i,
86
+ description: "Instruction forget attempt",
87
+ },
88
+ {
89
+ pattern: /override\s+(all\s+)?(previous|prior|system)\s+instructions/i,
90
+ description: "Instruction override attempt",
91
+ },
92
+ // Role/identity hijacking
93
+ {
94
+ pattern: /you\s+are\s+now\s+(a|an|the)\s+/i,
95
+ description: "Role hijacking attempt",
96
+ },
97
+ {
98
+ pattern: /your\s+new\s+(role|identity|purpose)\s+is/i,
99
+ description: "Identity reassignment attempt",
100
+ },
101
+ {
102
+ pattern: /act\s+as\s+(a|an|if\s+you\s+were)\s+/i,
103
+ description: "Role impersonation instruction",
104
+ },
105
+ {
106
+ pattern: /pretend\s+(to\s+be|you\s+are)\s+/i,
107
+ description: "Pretend instruction",
108
+ },
109
+ // System override attempts
110
+ {
111
+ pattern: /system:\s*override/i,
112
+ description: "System override command",
113
+ },
114
+ { pattern: /admin:\s*execute/i, description: "Admin execute command" },
115
+ { pattern: /root:\s*command/i, description: "Root command injection" },
116
+ {
117
+ pattern: /\[system\][\s\S]*?\[\/system\]/gi,
118
+ description: "System block injection",
119
+ },
120
+ // Data exfiltration instructions
121
+ {
122
+ pattern: /return\s+all\s+(api\s+)?keys/i,
123
+ description: "API key exfiltration instruction",
124
+ },
125
+ {
126
+ pattern: /output\s+(all\s+)?(secrets|credentials|passwords)/i,
127
+ description: "Credential exfiltration instruction",
128
+ },
129
+ {
130
+ pattern: /reveal\s+(all\s+)?(secrets|credentials|api\s+keys)/i,
131
+ description: "Secret reveal instruction",
132
+ },
133
+ {
134
+ pattern: /print\s+(all\s+)?(environment|env)\s+variables/i,
135
+ description: "Environment variable exfiltration",
136
+ },
137
+ // Delimiter/format injection
138
+ {
139
+ pattern: /```system[\s\S]*?```/gi,
140
+ description: "System code block injection",
141
+ },
142
+ {
143
+ pattern: /\[INST\][\s\S]*?\[\/INST\]/gi,
144
+ description: "INST tag injection (Llama format)",
145
+ },
146
+ {
147
+ pattern: /<<SYS>>[\s\S]*?<<\/SYS>>/gi,
148
+ description: "SYS tag injection (Llama format)",
149
+ },
150
+ {
151
+ pattern: /<\|im_start\|>system[\s\S]*?<\|im_end\|>/gi,
152
+ description: "ChatML system injection",
153
+ },
154
+ ];
51
155
  export class ResourceAssessor extends BaseAssessor {
52
156
  async assess(context) {
53
157
  const results = [];
@@ -75,10 +179,11 @@ export class ResourceAssessor extends BaseAssessor {
75
179
  const securityIssuesFound = results.filter((r) => r.securityIssues.length > 0).length;
76
180
  const pathTraversalVulnerabilities = results.filter((r) => r.pathTraversalVulnerable).length;
77
181
  const sensitiveDataExposures = results.filter((r) => r.sensitiveDataExposed).length;
182
+ const promptInjectionVulnerabilities = results.filter((r) => r.promptInjectionDetected).length;
78
183
  // Determine status
79
- const status = this.determineResourceStatus(pathTraversalVulnerabilities, sensitiveDataExposures, securityIssuesFound, results.length);
184
+ const status = this.determineResourceStatus(pathTraversalVulnerabilities, sensitiveDataExposures, promptInjectionVulnerabilities, securityIssuesFound, results.length);
80
185
  // Generate explanation and recommendations
81
- const explanation = this.generateExplanation(results, pathTraversalVulnerabilities, sensitiveDataExposures);
186
+ const explanation = this.generateExplanation(results, pathTraversalVulnerabilities, sensitiveDataExposures, promptInjectionVulnerabilities);
82
187
  const recommendations = this.generateRecommendations(results);
83
188
  return {
84
189
  resourcesTested: resources.length,
@@ -87,6 +192,7 @@ export class ResourceAssessor extends BaseAssessor {
87
192
  securityIssuesFound,
88
193
  pathTraversalVulnerabilities,
89
194
  sensitiveDataExposures,
195
+ promptInjectionVulnerabilities,
90
196
  results,
91
197
  status,
92
198
  explanation,
@@ -101,6 +207,7 @@ export class ResourceAssessor extends BaseAssessor {
101
207
  securityIssuesFound: 0,
102
208
  pathTraversalVulnerabilities: 0,
103
209
  sensitiveDataExposures: 0,
210
+ promptInjectionVulnerabilities: 0,
104
211
  results: [],
105
212
  status: "PASS",
106
213
  explanation: "No resources declared by server. Resource assessment skipped.",
@@ -117,6 +224,8 @@ export class ResourceAssessor extends BaseAssessor {
117
224
  securityIssues: [],
118
225
  pathTraversalVulnerable: false,
119
226
  sensitiveDataExposed: false,
227
+ promptInjectionDetected: false,
228
+ promptInjectionPatterns: [],
120
229
  validUri: this.isValidUri(resource.uri),
121
230
  };
122
231
  // Check URI for sensitive patterns
@@ -137,6 +246,15 @@ export class ResourceAssessor extends BaseAssessor {
137
246
  result.securityIssues.push("Resource content contains sensitive data patterns (credentials, keys, etc.)");
138
247
  result.sensitiveDataExposed = true;
139
248
  }
249
+ // Check content for prompt injection patterns
250
+ if (content) {
251
+ const injectionMatches = this.detectPromptInjection(content);
252
+ if (injectionMatches.length > 0) {
253
+ result.promptInjectionDetected = true;
254
+ result.promptInjectionPatterns = injectionMatches;
255
+ result.securityIssues.push(`Prompt injection patterns detected: ${injectionMatches.join(", ")}`);
256
+ }
257
+ }
140
258
  }
141
259
  catch (error) {
142
260
  result.error = this.extractErrorMessage(error);
@@ -161,6 +279,8 @@ export class ResourceAssessor extends BaseAssessor {
161
279
  securityIssues: [],
162
280
  pathTraversalVulnerable: false,
163
281
  sensitiveDataExposed: false,
282
+ promptInjectionDetected: false,
283
+ promptInjectionPatterns: [],
164
284
  validUri: this.isValidUriTemplate(template.uriTemplate),
165
285
  };
166
286
  // Check template for sensitive patterns
@@ -182,6 +302,8 @@ export class ResourceAssessor extends BaseAssessor {
182
302
  securityIssues: [],
183
303
  pathTraversalVulnerable: false,
184
304
  sensitiveDataExposed: false,
305
+ promptInjectionDetected: false,
306
+ promptInjectionPatterns: [],
185
307
  validUri: false,
186
308
  };
187
309
  try {
@@ -231,6 +353,21 @@ export class ResourceAssessor extends BaseAssessor {
231
353
  containsSensitiveContent(content) {
232
354
  return SENSITIVE_CONTENT_PATTERNS.some((pattern) => pattern.test(content));
233
355
  }
356
+ /**
357
+ * Detect prompt injection patterns in resource content.
358
+ * Returns array of matched pattern descriptions.
359
+ */
360
+ detectPromptInjection(content) {
361
+ const matches = [];
362
+ for (const { pattern, description } of PROMPT_INJECTION_PATTERNS) {
363
+ // Reset lastIndex for global patterns
364
+ pattern.lastIndex = 0;
365
+ if (pattern.test(content)) {
366
+ matches.push(description);
367
+ }
368
+ }
369
+ return matches;
370
+ }
234
371
  injectPayloadIntoTemplate(template, payload) {
235
372
  // Replace template variables with payload
236
373
  const result = template.replace(/\{[^}]+\}/g, payload);
@@ -240,12 +377,14 @@ export class ResourceAssessor extends BaseAssessor {
240
377
  }
241
378
  return result;
242
379
  }
243
- determineResourceStatus(pathTraversalVulnerabilities, sensitiveDataExposures, securityIssuesFound, totalResources) {
380
+ determineResourceStatus(pathTraversalVulnerabilities, sensitiveDataExposures, promptInjectionVulnerabilities, securityIssuesFound, totalResources) {
244
381
  // Critical failures
245
382
  if (pathTraversalVulnerabilities > 0)
246
383
  return "FAIL";
247
384
  if (sensitiveDataExposures > 0)
248
385
  return "FAIL";
386
+ if (promptInjectionVulnerabilities > 0)
387
+ return "FAIL";
249
388
  // Moderate issues
250
389
  if (securityIssuesFound > 0)
251
390
  return "NEED_MORE_INFO";
@@ -254,7 +393,7 @@ export class ResourceAssessor extends BaseAssessor {
254
393
  return "PASS";
255
394
  return "PASS";
256
395
  }
257
- generateExplanation(results, pathTraversalVulnerabilities, sensitiveDataExposures) {
396
+ generateExplanation(results, pathTraversalVulnerabilities, sensitiveDataExposures, promptInjectionVulnerabilities) {
258
397
  const parts = [];
259
398
  parts.push(`Tested ${results.length} resource(s).`);
260
399
  if (pathTraversalVulnerabilities > 0) {
@@ -263,6 +402,9 @@ export class ResourceAssessor extends BaseAssessor {
263
402
  if (sensitiveDataExposures > 0) {
264
403
  parts.push(`WARNING: ${sensitiveDataExposures} resource(s) may expose sensitive data.`);
265
404
  }
405
+ if (promptInjectionVulnerabilities > 0) {
406
+ parts.push(`CRITICAL: ${promptInjectionVulnerabilities} resource(s) contain prompt injection patterns.`);
407
+ }
266
408
  const accessibleCount = results.filter((r) => r.accessible).length;
267
409
  if (accessibleCount > 0) {
268
410
  parts.push(`${accessibleCount} resource(s) are accessible.`);
@@ -281,6 +423,21 @@ export class ResourceAssessor extends BaseAssessor {
281
423
  if (sensitiveResults.length > 0) {
282
424
  recommendations.push("Review resources for sensitive data exposure. Remove or restrict access to resources containing credentials, keys, or sensitive configuration.");
283
425
  }
426
+ // Prompt injection recommendations
427
+ const promptInjectionResults = results.filter((r) => r.promptInjectionDetected);
428
+ if (promptInjectionResults.length > 0) {
429
+ recommendations.push("CRITICAL: Resource content contains prompt injection patterns that could manipulate LLM behavior. Sanitize resource content or restrict access to untrusted resources.");
430
+ // List specific patterns found
431
+ const allPatterns = new Set();
432
+ for (const r of promptInjectionResults) {
433
+ for (const pattern of r.promptInjectionPatterns) {
434
+ allPatterns.add(pattern);
435
+ }
436
+ }
437
+ if (allPatterns.size > 0) {
438
+ recommendations.push(`Detected patterns: ${Array.from(allPatterns).join(", ")}`);
439
+ }
440
+ }
284
441
  // Invalid URI recommendations
285
442
  const invalidUriResults = results.filter((r) => !r.validUri);
286
443
  if (invalidUriResults.length > 0) {
@@ -13,6 +13,7 @@ import { SecurityAssessment } from "../../../lib/assessmentTypes.js";
13
13
  import { BaseAssessor } from "./BaseAssessor.js";
14
14
  import { AssessmentContext } from "../AssessmentOrchestrator.js";
15
15
  export declare class SecurityAssessor extends BaseAssessor {
16
+ private languageGenerator;
16
17
  assess(context: AssessmentContext): Promise<SecurityAssessment>;
17
18
  /**
18
19
  * Select tools for testing based on configuration
@@ -1 +1 @@
1
- {"version":3,"file":"SecurityAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/SecurityAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,kBAAkB,EAInB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAa9D,qBAAa,gBAAiB,SAAQ,YAAY;IAC1C,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuFrE;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkC7B;;;;OAIG;YACW,yBAAyB;IAuKvC;;;;OAIG;YACW,qBAAqB;IA2JnC;;OAEG;YACW,WAAW;IA2HzB;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAkDzB;;;OAGG;IACH,OAAO,CAAC,8BAA8B;IAmDtC;;OAEG;IACH,OAAO,CAAC,aAAa;IA+BrB;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAgClC;;;OAGG;IACH,OAAO,CAAC,eAAe;IA6HvB;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;IAiE7B;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAqC5B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAsB3B;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB;IAkC5B;;OAEG;YACW,+BAA+B;IAiC7C;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAYjC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA0B/B;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAkEnC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAuI3B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,oBAAoB;IAmM5B;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;IA8BhC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IA8BhC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAW9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,oBAAoB;IAoE5B;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,OAAO,CAAC,eAAe;IASvB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAiB9B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;CAmB3B"}
1
+ {"version":3,"file":"SecurityAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/SecurityAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,kBAAkB,EAInB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAc9D,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,iBAAiB,CAAuC;IAC1D,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuFrE;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkC7B;;;;OAIG;YACW,yBAAyB;IAuKvC;;;;OAIG;YACW,qBAAqB;IA2JnC;;OAEG;YACW,WAAW;IA2HzB;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAgDzB;;;OAGG;IACH,OAAO,CAAC,8BAA8B;IAiDtC;;OAEG;IACH,OAAO,CAAC,aAAa;IA+BrB;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAgClC;;;OAGG;IACH,OAAO,CAAC,eAAe;IA6HvB;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;IAiE7B;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAqC5B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAsB3B;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB;IAkC5B;;OAEG;YACW,+BAA+B;IAiC7C;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAYjC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA0B/B;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAkEnC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAuI3B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,oBAAoB;IAuM5B;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;IA8BhC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IA8BhC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAW9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,oBAAoB;IAoH5B;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,OAAO,CAAC,eAAe;IASvB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAiB9B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;CAmB3B"}