@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.
- package/dist/assets/{OAuthCallback-DhwTOA1q.js → OAuthCallback-BDIUPkR-.js} +1 -1
- package/dist/assets/{OAuthDebugCallback-DzopkA29.js → OAuthDebugCallback-DPLV3zir.js} +1 -1
- package/dist/assets/{index-CzoGuYPy.css → index-32-uLPhe.css} +3 -0
- package/dist/assets/{index-zBRaltBB.js → index-DKTSB7VQ.js} +460 -27
- package/dist/index.html +2 -2
- package/lib/lib/assessmentTypes.d.ts +45 -2
- package/lib/lib/assessmentTypes.d.ts.map +1 -1
- package/lib/lib/securityPatterns.d.ts.map +1 -1
- package/lib/lib/securityPatterns.js +82 -2
- package/lib/services/assessment/AssessmentOrchestrator.d.ts +1 -0
- package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
- package/lib/services/assessment/AssessmentOrchestrator.js +5 -2
- package/lib/services/assessment/LanguageAwarePayloadGenerator.d.ts +41 -0
- package/lib/services/assessment/LanguageAwarePayloadGenerator.d.ts.map +1 -0
- package/lib/services/assessment/LanguageAwarePayloadGenerator.js +258 -0
- package/lib/services/assessment/ToolClassifier.d.ts +1 -0
- package/lib/services/assessment/ToolClassifier.d.ts.map +1 -1
- package/lib/services/assessment/ToolClassifier.js +26 -0
- package/lib/services/assessment/modules/ResourceAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ResourceAssessor.js +161 -4
- package/lib/services/assessment/modules/SecurityAssessor.d.ts +1 -0
- package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/SecurityAssessor.js +49 -14
- package/lib/services/assessment/modules/TemporalAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/TemporalAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/TemporalAssessor.js +133 -15
- package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ToolAnnotationAssessor.js +256 -1
- 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
|
+
}
|
|
@@ -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;
|
|
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;
|
|
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;
|
|
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"}
|