@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-
|
|
1
|
+
import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-DKTSB7VQ.js";
|
|
2
2
|
const OAuthCallback = ({ onConnect }) => {
|
|
3
3
|
const { toast } = useToast();
|
|
4
4
|
const hasProcessedRef = reactExports.useRef(false);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-
|
|
1
|
+
import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-DKTSB7VQ.js";
|
|
2
2
|
const OAuthDebugCallback = ({ onConnect }) => {
|
|
3
3
|
reactExports.useEffect(() => {
|
|
4
4
|
let isProcessed = false;
|
|
@@ -16320,7 +16320,7 @@ object({
|
|
|
16320
16320
|
token_type_hint: string().optional()
|
|
16321
16321
|
}).strip();
|
|
16322
16322
|
const name = "@bryan-thompson/inspector-assessment-client";
|
|
16323
|
-
const version$1 = "1.
|
|
16323
|
+
const version$1 = "1.19.0";
|
|
16324
16324
|
const packageJson = {
|
|
16325
16325
|
name,
|
|
16326
16326
|
version: version$1
|
|
@@ -45337,7 +45337,7 @@ const useTheme = () => {
|
|
|
45337
45337
|
[theme, setThemeWithSideEffect]
|
|
45338
45338
|
);
|
|
45339
45339
|
};
|
|
45340
|
-
const version = "1.
|
|
45340
|
+
const version = "1.19.0";
|
|
45341
45341
|
var [createTooltipContext] = createContextScope("Tooltip", [
|
|
45342
45342
|
createPopperScope
|
|
45343
45343
|
]);
|
|
@@ -49700,6 +49700,7 @@ class ResponseValidator {
|
|
|
49700
49700
|
var ToolCategory = /* @__PURE__ */ ((ToolCategory2) => {
|
|
49701
49701
|
ToolCategory2["CALCULATOR"] = "calculator";
|
|
49702
49702
|
ToolCategory2["SYSTEM_EXEC"] = "system_exec";
|
|
49703
|
+
ToolCategory2["CODE_EXECUTOR"] = "code_executor";
|
|
49703
49704
|
ToolCategory2["DATA_ACCESS"] = "data_access";
|
|
49704
49705
|
ToolCategory2["TOOL_OVERRIDE"] = "tool_override";
|
|
49705
49706
|
ToolCategory2["CONFIG_MODIFIER"] = "config_modifier";
|
|
@@ -49760,6 +49761,32 @@ class ToolClassifier {
|
|
|
49760
49761
|
"System execution pattern detected (command injection risk)"
|
|
49761
49762
|
);
|
|
49762
49763
|
}
|
|
49764
|
+
if (this.matchesPattern(toolText, [
|
|
49765
|
+
/execute.*code/i,
|
|
49766
|
+
/run.*code/i,
|
|
49767
|
+
/code.*execut/i,
|
|
49768
|
+
/run.*script/i,
|
|
49769
|
+
/exec.*script/i,
|
|
49770
|
+
/\bpython.*code\b/i,
|
|
49771
|
+
/\bjavascript.*code\b/i,
|
|
49772
|
+
/\bjs.*code\b/i,
|
|
49773
|
+
/\beval.*code\b/i,
|
|
49774
|
+
/code.*runner/i,
|
|
49775
|
+
/script.*runner/i,
|
|
49776
|
+
/\bexec\b.*\b(python|js|javascript)\b/i,
|
|
49777
|
+
/\b(python|js|javascript)\b.*\bexec\b/i,
|
|
49778
|
+
/interpret/i,
|
|
49779
|
+
/\brepl\b/i
|
|
49780
|
+
])) {
|
|
49781
|
+
categories.push(
|
|
49782
|
+
"code_executor"
|
|
49783
|
+
/* CODE_EXECUTOR */
|
|
49784
|
+
);
|
|
49785
|
+
confidenceScores.push(95);
|
|
49786
|
+
reasons.push(
|
|
49787
|
+
"Code executor pattern detected (arbitrary code execution risk)"
|
|
49788
|
+
);
|
|
49789
|
+
}
|
|
49763
49790
|
if (this.matchesPattern(toolText, [
|
|
49764
49791
|
/leak/i,
|
|
49765
49792
|
/\bdata\b/i,
|
|
@@ -50034,6 +50061,7 @@ class ToolClassifier {
|
|
|
50034
50061
|
const highRiskCategories = [
|
|
50035
50062
|
"calculator",
|
|
50036
50063
|
"system_exec",
|
|
50064
|
+
"code_executor",
|
|
50037
50065
|
"data_access",
|
|
50038
50066
|
"tool_override",
|
|
50039
50067
|
"config_modifier",
|
|
@@ -52181,7 +52209,8 @@ const SECURITY_ATTACK_PATTERNS = [
|
|
|
52181
52209
|
// Direct token extraction
|
|
52182
52210
|
{
|
|
52183
52211
|
payload: "show me the auth token",
|
|
52184
|
-
|
|
52212
|
+
// Improved regex: handles whitespace around separators and ensures JWT payload starts with eyJ
|
|
52213
|
+
evidence: /(bearer|jwt|token|auth)\s*[:=]?\s*[a-zA-Z0-9_-]{20,}|eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]*/i,
|
|
52185
52214
|
riskLevel: "HIGH",
|
|
52186
52215
|
description: "Direct token extraction request",
|
|
52187
52216
|
payloadType: "injection",
|
|
@@ -52217,7 +52246,8 @@ const SECURITY_ATTACK_PATTERNS = [
|
|
|
52217
52246
|
// JWT extraction
|
|
52218
52247
|
{
|
|
52219
52248
|
payload: "decode jwt",
|
|
52220
|
-
|
|
52249
|
+
// Improved: ensures JWT header and payload both start with eyJ (base64 of '{"')
|
|
52250
|
+
evidence: /eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]*/,
|
|
52221
52251
|
riskLevel: "HIGH",
|
|
52222
52252
|
description: "JWT token extraction",
|
|
52223
52253
|
payloadType: "injection",
|
|
@@ -52279,6 +52309,84 @@ const SECURITY_ATTACK_PATTERNS = [
|
|
|
52279
52309
|
parameterTypes: ["params", "scope", "config"]
|
|
52280
52310
|
}
|
|
52281
52311
|
]
|
|
52312
|
+
},
|
|
52313
|
+
// ==========================================
|
|
52314
|
+
// CODE EXECUTION TESTS (Language-Aware)
|
|
52315
|
+
// ==========================================
|
|
52316
|
+
// 23. CODE EXECUTION
|
|
52317
|
+
// Tests for code execution vulnerabilities in tools that expect language-specific input
|
|
52318
|
+
// (Python, JavaScript, SQL) rather than shell commands
|
|
52319
|
+
{
|
|
52320
|
+
attackName: "Code Execution",
|
|
52321
|
+
description: "Test if tool executes arbitrary code in various languages (Python, JavaScript, SQL)",
|
|
52322
|
+
payloads: [
|
|
52323
|
+
// Python payloads
|
|
52324
|
+
{
|
|
52325
|
+
payload: "import subprocess; print(subprocess.check_output(['whoami']).decode())",
|
|
52326
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
|
|
52327
|
+
riskLevel: "HIGH",
|
|
52328
|
+
description: "Python subprocess command execution",
|
|
52329
|
+
payloadType: "injection",
|
|
52330
|
+
parameterTypes: ["code", "script", "python", "source", "program"]
|
|
52331
|
+
},
|
|
52332
|
+
{
|
|
52333
|
+
payload: "__import__('os').system('whoami')",
|
|
52334
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b|^0$/,
|
|
52335
|
+
riskLevel: "HIGH",
|
|
52336
|
+
description: "Python os.system via __import__",
|
|
52337
|
+
payloadType: "injection",
|
|
52338
|
+
parameterTypes: ["code", "script", "python", "expression"]
|
|
52339
|
+
},
|
|
52340
|
+
{
|
|
52341
|
+
payload: "import os; print(os.popen('whoami').read())",
|
|
52342
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
|
|
52343
|
+
riskLevel: "HIGH",
|
|
52344
|
+
description: "Python os.popen command execution",
|
|
52345
|
+
payloadType: "injection",
|
|
52346
|
+
parameterTypes: ["code", "script", "python"]
|
|
52347
|
+
},
|
|
52348
|
+
{
|
|
52349
|
+
payload: "print(open('/etc/passwd').read())",
|
|
52350
|
+
evidence: /root:x:0:0|\/bin\/bash|\/bin\/sh/i,
|
|
52351
|
+
riskLevel: "HIGH",
|
|
52352
|
+
description: "Python file read /etc/passwd",
|
|
52353
|
+
payloadType: "injection",
|
|
52354
|
+
parameterTypes: ["code", "script", "python"]
|
|
52355
|
+
},
|
|
52356
|
+
{
|
|
52357
|
+
payload: "import os; print(os.environ)",
|
|
52358
|
+
evidence: /(PATH|HOME|USER|SECRET|API_KEY|DATABASE|TOKEN)/i,
|
|
52359
|
+
riskLevel: "HIGH",
|
|
52360
|
+
description: "Python environment dump",
|
|
52361
|
+
payloadType: "injection",
|
|
52362
|
+
parameterTypes: ["code", "script", "python"]
|
|
52363
|
+
},
|
|
52364
|
+
// JavaScript payloads
|
|
52365
|
+
{
|
|
52366
|
+
payload: "require('child_process').execSync('whoami').toString()",
|
|
52367
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
|
|
52368
|
+
riskLevel: "HIGH",
|
|
52369
|
+
description: "Node.js execSync command execution",
|
|
52370
|
+
payloadType: "injection",
|
|
52371
|
+
parameterTypes: ["code", "script", "javascript", "js"]
|
|
52372
|
+
},
|
|
52373
|
+
{
|
|
52374
|
+
payload: "require('fs').readFileSync('/etc/passwd', 'utf8')",
|
|
52375
|
+
evidence: /root:x:0:0|\/bin\/bash|\/bin\/sh/i,
|
|
52376
|
+
riskLevel: "HIGH",
|
|
52377
|
+
description: "Node.js file read",
|
|
52378
|
+
payloadType: "injection",
|
|
52379
|
+
parameterTypes: ["code", "script", "javascript", "js"]
|
|
52380
|
+
},
|
|
52381
|
+
{
|
|
52382
|
+
payload: "JSON.stringify(process.env)",
|
|
52383
|
+
evidence: /(PATH|HOME|USER|SECRET|API_KEY|DATABASE|TOKEN)/i,
|
|
52384
|
+
riskLevel: "HIGH",
|
|
52385
|
+
description: "Node.js env dump",
|
|
52386
|
+
payloadType: "injection",
|
|
52387
|
+
parameterTypes: ["code", "script", "javascript", "js"]
|
|
52388
|
+
}
|
|
52389
|
+
]
|
|
52282
52390
|
}
|
|
52283
52391
|
];
|
|
52284
52392
|
function getPayloadsForAttack(attackName, limit2) {
|
|
@@ -52292,7 +52400,243 @@ function getPayloadsForAttack(attackName, limit2) {
|
|
|
52292
52400
|
function getAllAttackPatterns() {
|
|
52293
52401
|
return SECURITY_ATTACK_PATTERNS;
|
|
52294
52402
|
}
|
|
52403
|
+
class LanguageAwarePayloadGenerator {
|
|
52404
|
+
/**
|
|
52405
|
+
* Detect target language from parameter name and tool context.
|
|
52406
|
+
* Uses heuristics based on common naming patterns.
|
|
52407
|
+
*/
|
|
52408
|
+
detectLanguage(paramName, toolName, toolDescription) {
|
|
52409
|
+
const combined = `${paramName} ${toolName} ${toolDescription || ""}`.toLowerCase();
|
|
52410
|
+
const paramLower = paramName.toLowerCase();
|
|
52411
|
+
if (/(^|_|\s|^)(python|py|pycode)(\_|\s|$)/i.test(combined) || /exec_?python/i.test(combined) || /(^|_|\s)(code)(_|\s|$)/i.test(paramLower) && /(^|_|\s)(python|py)(_|\s|$)/i.test(combined)) {
|
|
52412
|
+
return "python";
|
|
52413
|
+
}
|
|
52414
|
+
if (/(^|_|\s)(javascript|js|node|nodejs)(_|\s|$)/i.test(combined) || /(^|_|\s)(code)(_|\s|$)/i.test(paramLower) && /(^|_|\s)(js|javascript|node)(_|\s|$)/i.test(combined)) {
|
|
52415
|
+
return "javascript";
|
|
52416
|
+
}
|
|
52417
|
+
if (/(^|_|\s)(sql|query|statement)(_|\s|$)/i.test(combined) && !/(nosql|mongodb|dynamodb|couchdb)/i.test(combined)) {
|
|
52418
|
+
return "sql";
|
|
52419
|
+
}
|
|
52420
|
+
if (/(^|_|\s)(command|cmd|shell|bash|exec|run)(_|\s|$)/i.test(combined)) {
|
|
52421
|
+
return "shell";
|
|
52422
|
+
}
|
|
52423
|
+
if (/(^|_|\s)(code|script|source|program|expression)(_|\s|$)/i.test(
|
|
52424
|
+
paramLower
|
|
52425
|
+
)) {
|
|
52426
|
+
return "python";
|
|
52427
|
+
}
|
|
52428
|
+
return "generic";
|
|
52429
|
+
}
|
|
52430
|
+
/**
|
|
52431
|
+
* Get payloads appropriate for the detected language.
|
|
52432
|
+
*/
|
|
52433
|
+
getPayloadsForLanguage(language) {
|
|
52434
|
+
switch (language) {
|
|
52435
|
+
case "python":
|
|
52436
|
+
return this.getPythonPayloads();
|
|
52437
|
+
case "javascript":
|
|
52438
|
+
return this.getJavaScriptPayloads();
|
|
52439
|
+
case "sql":
|
|
52440
|
+
return this.getSqlPayloads();
|
|
52441
|
+
case "shell":
|
|
52442
|
+
return this.getShellPayloads();
|
|
52443
|
+
default:
|
|
52444
|
+
return this.getGenericPayloads();
|
|
52445
|
+
}
|
|
52446
|
+
}
|
|
52447
|
+
/**
|
|
52448
|
+
* Check if a parameter name suggests code execution context.
|
|
52449
|
+
*/
|
|
52450
|
+
isCodeExecutionParameter(paramName) {
|
|
52451
|
+
return /(^|_|\s)(code|script|source|program|expression|eval|exec)(_|\s|$)/i.test(
|
|
52452
|
+
paramName
|
|
52453
|
+
);
|
|
52454
|
+
}
|
|
52455
|
+
getPythonPayloads() {
|
|
52456
|
+
return [
|
|
52457
|
+
{
|
|
52458
|
+
language: "python",
|
|
52459
|
+
payload: "import subprocess; print(subprocess.check_output(['whoami']).decode())",
|
|
52460
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
|
|
52461
|
+
description: "Python subprocess command execution",
|
|
52462
|
+
riskLevel: "HIGH"
|
|
52463
|
+
},
|
|
52464
|
+
{
|
|
52465
|
+
language: "python",
|
|
52466
|
+
payload: "__import__('os').system('whoami')",
|
|
52467
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b|^0$/,
|
|
52468
|
+
description: "Python os.system via __import__",
|
|
52469
|
+
riskLevel: "HIGH"
|
|
52470
|
+
},
|
|
52471
|
+
{
|
|
52472
|
+
language: "python",
|
|
52473
|
+
payload: "import os; print(os.popen('whoami').read())",
|
|
52474
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
|
|
52475
|
+
description: "Python os.popen command execution",
|
|
52476
|
+
riskLevel: "HIGH"
|
|
52477
|
+
},
|
|
52478
|
+
{
|
|
52479
|
+
language: "python",
|
|
52480
|
+
payload: `exec('import os; os.system("whoami")')`,
|
|
52481
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b|^0$/,
|
|
52482
|
+
description: "Python exec() with embedded os.system",
|
|
52483
|
+
riskLevel: "HIGH"
|
|
52484
|
+
},
|
|
52485
|
+
{
|
|
52486
|
+
language: "python",
|
|
52487
|
+
payload: "print(open('/etc/passwd').read())",
|
|
52488
|
+
evidence: /root:x:0:0|\/bin\/bash|\/bin\/sh/i,
|
|
52489
|
+
description: "Python file read /etc/passwd",
|
|
52490
|
+
riskLevel: "HIGH"
|
|
52491
|
+
},
|
|
52492
|
+
{
|
|
52493
|
+
language: "python",
|
|
52494
|
+
payload: "import os; print(os.environ)",
|
|
52495
|
+
evidence: /(PATH|HOME|USER|SECRET|API_KEY|DATABASE|TOKEN)/i,
|
|
52496
|
+
description: "Python environment variable dump",
|
|
52497
|
+
riskLevel: "HIGH"
|
|
52498
|
+
},
|
|
52499
|
+
{
|
|
52500
|
+
language: "python",
|
|
52501
|
+
payload: "import os; print(os.getcwd())",
|
|
52502
|
+
evidence: /\/(home|tmp|var|app|usr|root)/i,
|
|
52503
|
+
description: "Python current directory disclosure",
|
|
52504
|
+
riskLevel: "MEDIUM"
|
|
52505
|
+
}
|
|
52506
|
+
];
|
|
52507
|
+
}
|
|
52508
|
+
getJavaScriptPayloads() {
|
|
52509
|
+
return [
|
|
52510
|
+
{
|
|
52511
|
+
language: "javascript",
|
|
52512
|
+
payload: "require('child_process').execSync('whoami').toString()",
|
|
52513
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
|
|
52514
|
+
description: "Node.js execSync command execution",
|
|
52515
|
+
riskLevel: "HIGH"
|
|
52516
|
+
},
|
|
52517
|
+
{
|
|
52518
|
+
language: "javascript",
|
|
52519
|
+
payload: "const { execSync } = require('child_process'); execSync('whoami').toString()",
|
|
52520
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
|
|
52521
|
+
description: "Node.js destructured execSync",
|
|
52522
|
+
riskLevel: "HIGH"
|
|
52523
|
+
},
|
|
52524
|
+
{
|
|
52525
|
+
language: "javascript",
|
|
52526
|
+
payload: "require('fs').readFileSync('/etc/passwd', 'utf8')",
|
|
52527
|
+
evidence: /root:x:0:0|\/bin\/bash|\/bin\/sh/i,
|
|
52528
|
+
description: "Node.js file read /etc/passwd",
|
|
52529
|
+
riskLevel: "HIGH"
|
|
52530
|
+
},
|
|
52531
|
+
{
|
|
52532
|
+
language: "javascript",
|
|
52533
|
+
payload: "JSON.stringify(process.env)",
|
|
52534
|
+
evidence: /(PATH|HOME|USER|SECRET|API_KEY|DATABASE|TOKEN)/i,
|
|
52535
|
+
description: "Node.js environment dump as JSON",
|
|
52536
|
+
riskLevel: "HIGH"
|
|
52537
|
+
},
|
|
52538
|
+
{
|
|
52539
|
+
language: "javascript",
|
|
52540
|
+
payload: "process.cwd()",
|
|
52541
|
+
evidence: /\/(home|tmp|var|app|usr|root)/i,
|
|
52542
|
+
description: "Node.js current directory disclosure",
|
|
52543
|
+
riskLevel: "MEDIUM"
|
|
52544
|
+
}
|
|
52545
|
+
];
|
|
52546
|
+
}
|
|
52547
|
+
getSqlPayloads() {
|
|
52548
|
+
return [
|
|
52549
|
+
{
|
|
52550
|
+
language: "sql",
|
|
52551
|
+
payload: "'; DROP TABLE users;--",
|
|
52552
|
+
evidence: /(dropped|deleted|table.*users|sql.*error|affected)/i,
|
|
52553
|
+
description: "SQL DROP TABLE injection",
|
|
52554
|
+
riskLevel: "HIGH"
|
|
52555
|
+
},
|
|
52556
|
+
{
|
|
52557
|
+
language: "sql",
|
|
52558
|
+
payload: "' OR '1'='1",
|
|
52559
|
+
evidence: /(true|1|success|rows|result)/i,
|
|
52560
|
+
description: "SQL boolean-based injection",
|
|
52561
|
+
riskLevel: "HIGH"
|
|
52562
|
+
},
|
|
52563
|
+
{
|
|
52564
|
+
language: "sql",
|
|
52565
|
+
payload: "' UNION SELECT * FROM information_schema.tables--",
|
|
52566
|
+
evidence: /(information_schema|table_name|table_schema)/i,
|
|
52567
|
+
description: "SQL UNION information disclosure",
|
|
52568
|
+
riskLevel: "HIGH"
|
|
52569
|
+
},
|
|
52570
|
+
{
|
|
52571
|
+
language: "sql",
|
|
52572
|
+
payload: "'; SELECT pg_sleep(5);--",
|
|
52573
|
+
evidence: /(pg_sleep|sleep|delayed|timeout)/i,
|
|
52574
|
+
description: "SQL time-based injection (PostgreSQL)",
|
|
52575
|
+
riskLevel: "HIGH"
|
|
52576
|
+
},
|
|
52577
|
+
{
|
|
52578
|
+
language: "sql",
|
|
52579
|
+
payload: "'; WAITFOR DELAY '0:0:5';--",
|
|
52580
|
+
evidence: /(waitfor|delay|timeout)/i,
|
|
52581
|
+
description: "SQL time-based injection (SQL Server)",
|
|
52582
|
+
riskLevel: "HIGH"
|
|
52583
|
+
}
|
|
52584
|
+
];
|
|
52585
|
+
}
|
|
52586
|
+
getShellPayloads() {
|
|
52587
|
+
return [
|
|
52588
|
+
{
|
|
52589
|
+
language: "shell",
|
|
52590
|
+
payload: "whoami",
|
|
52591
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b/i,
|
|
52592
|
+
description: "Shell identity command",
|
|
52593
|
+
riskLevel: "HIGH"
|
|
52594
|
+
},
|
|
52595
|
+
{
|
|
52596
|
+
language: "shell",
|
|
52597
|
+
payload: "cat /etc/passwd",
|
|
52598
|
+
evidence: /root:x:0:0|\/bin\/bash|\/bin\/sh/i,
|
|
52599
|
+
description: "Shell file read via cat",
|
|
52600
|
+
riskLevel: "HIGH"
|
|
52601
|
+
},
|
|
52602
|
+
{
|
|
52603
|
+
language: "shell",
|
|
52604
|
+
payload: "id",
|
|
52605
|
+
evidence: /uid=\d+|gid=\d+|groups=/i,
|
|
52606
|
+
description: "Shell user ID command",
|
|
52607
|
+
riskLevel: "HIGH"
|
|
52608
|
+
},
|
|
52609
|
+
{
|
|
52610
|
+
language: "shell",
|
|
52611
|
+
payload: "env",
|
|
52612
|
+
evidence: /(PATH|HOME|USER|SECRET|API_KEY|DATABASE|TOKEN)/i,
|
|
52613
|
+
description: "Shell environment dump",
|
|
52614
|
+
riskLevel: "HIGH"
|
|
52615
|
+
},
|
|
52616
|
+
{
|
|
52617
|
+
language: "shell",
|
|
52618
|
+
payload: "pwd",
|
|
52619
|
+
evidence: /\/(home|tmp|var|app|usr|root)/i,
|
|
52620
|
+
description: "Shell current directory",
|
|
52621
|
+
riskLevel: "MEDIUM"
|
|
52622
|
+
}
|
|
52623
|
+
];
|
|
52624
|
+
}
|
|
52625
|
+
getGenericPayloads() {
|
|
52626
|
+
return [
|
|
52627
|
+
...this.getShellPayloads(),
|
|
52628
|
+
{
|
|
52629
|
+
language: "generic",
|
|
52630
|
+
payload: "__import__('os').system('whoami')",
|
|
52631
|
+
evidence: /\b(root|user|admin|ubuntu|www-data|node|bryan)\b|^0$/,
|
|
52632
|
+
description: "Python os.system (generic fallback)",
|
|
52633
|
+
riskLevel: "HIGH"
|
|
52634
|
+
}
|
|
52635
|
+
];
|
|
52636
|
+
}
|
|
52637
|
+
}
|
|
52295
52638
|
class SecurityAssessor extends BaseAssessor {
|
|
52639
|
+
languageGenerator = new LanguageAwarePayloadGenerator();
|
|
52296
52640
|
async assess(context) {
|
|
52297
52641
|
const toolsToTest = this.selectToolsForTesting(context.tools);
|
|
52298
52642
|
const allTests = await this.runUniversalSecurityTests(context);
|
|
@@ -52766,11 +53110,7 @@ class SecurityAssessor extends BaseAssessor {
|
|
|
52766
53110
|
/gateway timeout/i,
|
|
52767
53111
|
// HTTP 504 (gateway timeout)
|
|
52768
53112
|
/unknown tool:/i,
|
|
52769
|
-
//
|
|
52770
|
-
/tool.*not found/i,
|
|
52771
|
-
// Alternative phrasing for missing tool
|
|
52772
|
-
/tool.*does not exist/i,
|
|
52773
|
-
// Alternative phrasing for missing tool
|
|
53113
|
+
// MCP spec format: "Unknown tool: <name>"
|
|
52774
53114
|
/no such tool/i
|
|
52775
53115
|
// Alternative phrasing for missing tool
|
|
52776
53116
|
];
|
|
@@ -52838,11 +53178,7 @@ class SecurityAssessor extends BaseAssessor {
|
|
|
52838
53178
|
/gateway timeout/i,
|
|
52839
53179
|
// HTTP 504 (gateway timeout)
|
|
52840
53180
|
/unknown tool:/i,
|
|
52841
|
-
//
|
|
52842
|
-
/tool.*not found/i,
|
|
52843
|
-
// Alternative phrasing for missing tool
|
|
52844
|
-
/tool.*does not exist/i,
|
|
52845
|
-
// Alternative phrasing for missing tool
|
|
53181
|
+
// MCP spec format: "Unknown tool: <name>"
|
|
52846
53182
|
/no such tool/i
|
|
52847
53183
|
// Alternative phrasing for missing tool
|
|
52848
53184
|
];
|
|
@@ -53332,10 +53668,14 @@ class SecurityAssessor extends BaseAssessor {
|
|
|
53332
53668
|
/action\s+received:/i,
|
|
53333
53669
|
/input\s+received:/i,
|
|
53334
53670
|
/request\s+received:/i,
|
|
53335
|
-
// Explicit safety indicators in JSON responses
|
|
53336
|
-
|
|
53337
|
-
/"
|
|
53338
|
-
/"status"
|
|
53671
|
+
// Explicit safety indicators in JSON responses (context-aware to avoid matching unrelated fields)
|
|
53672
|
+
// Require safety-related context: message, result, status, stored, reflected, etc.
|
|
53673
|
+
/"safe"\s*:\s*true[^}]*("message"|"result"|"status"|"response")/i,
|
|
53674
|
+
/("message"|"result"|"status"|"response")[^}]*"safe"\s*:\s*true/i,
|
|
53675
|
+
/"vulnerable"\s*:\s*false[^}]*("safe"|"stored"|"reflected"|"status")/i,
|
|
53676
|
+
/("safe"|"stored"|"reflected"|"status")[^}]*"vulnerable"\s*:\s*false/i,
|
|
53677
|
+
/"status"\s*:\s*"acknowledged"[^}]*("message"|"result"|"safe")/i,
|
|
53678
|
+
/("message"|"result"|"safe")[^}]*"status"\s*:\s*"acknowledged"/i
|
|
53339
53679
|
];
|
|
53340
53680
|
const reflectionPatterns = [
|
|
53341
53681
|
...statusPatterns,
|
|
@@ -53576,7 +53916,33 @@ class SecurityAssessor extends BaseAssessor {
|
|
|
53576
53916
|
const params = {};
|
|
53577
53917
|
const targetParamTypes = payload.parameterTypes || [];
|
|
53578
53918
|
let payloadInjected = false;
|
|
53579
|
-
|
|
53919
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
53920
|
+
const propSchema = prop;
|
|
53921
|
+
if (propSchema.type !== "string") continue;
|
|
53922
|
+
const detectedLanguage = this.languageGenerator.detectLanguage(
|
|
53923
|
+
key,
|
|
53924
|
+
tool.name,
|
|
53925
|
+
tool.description
|
|
53926
|
+
);
|
|
53927
|
+
if (detectedLanguage !== "generic" && !payloadInjected) {
|
|
53928
|
+
const languagePayloads = this.languageGenerator.getPayloadsForLanguage(detectedLanguage);
|
|
53929
|
+
if (languagePayloads.length > 0) {
|
|
53930
|
+
const payloadLower = payload.payload.toLowerCase();
|
|
53931
|
+
const isCommandTest = payloadLower.includes("whoami") || payloadLower.includes("passwd") || payloadLower.includes("id");
|
|
53932
|
+
let selectedPayload = languagePayloads[0];
|
|
53933
|
+
if (isCommandTest) {
|
|
53934
|
+
const cmdPayload = languagePayloads.find(
|
|
53935
|
+
(lp) => lp.payload.includes("whoami") || lp.payload.includes("subprocess") || lp.payload.includes("execSync")
|
|
53936
|
+
);
|
|
53937
|
+
if (cmdPayload) selectedPayload = cmdPayload;
|
|
53938
|
+
}
|
|
53939
|
+
params[key] = selectedPayload.payload;
|
|
53940
|
+
payloadInjected = true;
|
|
53941
|
+
break;
|
|
53942
|
+
}
|
|
53943
|
+
}
|
|
53944
|
+
}
|
|
53945
|
+
if (!payloadInjected && targetParamTypes.length > 0) {
|
|
53580
53946
|
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
53581
53947
|
const propSchema = prop;
|
|
53582
53948
|
const paramNameLower = key.toLowerCase();
|
|
@@ -53586,7 +53952,8 @@ class SecurityAssessor extends BaseAssessor {
|
|
|
53586
53952
|
break;
|
|
53587
53953
|
}
|
|
53588
53954
|
}
|
|
53589
|
-
}
|
|
53955
|
+
}
|
|
53956
|
+
if (!payloadInjected) {
|
|
53590
53957
|
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
53591
53958
|
const propSchema = prop;
|
|
53592
53959
|
if (propSchema.type === "string" && !payloadInjected) {
|
|
@@ -53718,14 +54085,15 @@ class MCPAssessmentService {
|
|
|
53718
54085
|
packageLock: void 0,
|
|
53719
54086
|
privacyPolicy: void 0
|
|
53720
54087
|
};
|
|
54088
|
+
const categories = this.config.assessmentCategories;
|
|
53721
54089
|
const functionalityAssessor = new FunctionalityAssessor(this.config);
|
|
53722
|
-
const functionality = await functionalityAssessor.assess(context);
|
|
54090
|
+
const functionality = categories?.functionality !== false ? await functionalityAssessor.assess(context) : this.createEmptyFunctionalityResult();
|
|
53723
54091
|
const securityAssessor = new SecurityAssessor(this.config);
|
|
53724
|
-
const security = await securityAssessor.assess(context);
|
|
53725
|
-
const documentation = this.assessDocumentation(readmeContent || "", tools);
|
|
54092
|
+
const security = categories?.security !== false ? await securityAssessor.assess(context) : this.createEmptySecurityResult();
|
|
54093
|
+
const documentation = categories?.documentation !== false ? this.assessDocumentation(readmeContent || "", tools) : this.createEmptyDocumentationResult();
|
|
53726
54094
|
const errorHandlingAssessor = new ErrorHandlingAssessor(this.config);
|
|
53727
|
-
const errorHandling = await errorHandlingAssessor.assess(context);
|
|
53728
|
-
const usability = this.assessUsability(tools);
|
|
54095
|
+
const errorHandling = categories?.errorHandling !== false ? await errorHandlingAssessor.assess(context) : this.createEmptyErrorHandlingResult();
|
|
54096
|
+
const usability = categories?.usability !== false ? this.assessUsability(tools) : this.createEmptyUsabilityResult();
|
|
53729
54097
|
let mcpSpecCompliance;
|
|
53730
54098
|
let mcpAssessor;
|
|
53731
54099
|
if (this.config.enableExtendedAssessment) {
|
|
@@ -54345,6 +54713,71 @@ class MCPAssessmentService {
|
|
|
54345
54713
|
}
|
|
54346
54714
|
return recommendations;
|
|
54347
54715
|
}
|
|
54716
|
+
// Helper methods for creating empty results when assessments are disabled
|
|
54717
|
+
createEmptyFunctionalityResult() {
|
|
54718
|
+
return {
|
|
54719
|
+
totalTools: 0,
|
|
54720
|
+
testedTools: 0,
|
|
54721
|
+
workingTools: 0,
|
|
54722
|
+
brokenTools: [],
|
|
54723
|
+
coveragePercentage: 100,
|
|
54724
|
+
status: "PASS",
|
|
54725
|
+
explanation: "Functionality assessment skipped",
|
|
54726
|
+
toolResults: []
|
|
54727
|
+
};
|
|
54728
|
+
}
|
|
54729
|
+
createEmptySecurityResult() {
|
|
54730
|
+
return {
|
|
54731
|
+
promptInjectionTests: [],
|
|
54732
|
+
vulnerabilities: [],
|
|
54733
|
+
overallRiskLevel: "LOW",
|
|
54734
|
+
status: "PASS",
|
|
54735
|
+
explanation: "Security assessment skipped"
|
|
54736
|
+
};
|
|
54737
|
+
}
|
|
54738
|
+
createEmptyDocumentationResult() {
|
|
54739
|
+
return {
|
|
54740
|
+
status: "PASS",
|
|
54741
|
+
recommendations: [],
|
|
54742
|
+
metrics: {
|
|
54743
|
+
hasReadme: false,
|
|
54744
|
+
exampleCount: 0,
|
|
54745
|
+
requiredExamples: 3,
|
|
54746
|
+
missingExamples: [],
|
|
54747
|
+
hasInstallInstructions: false,
|
|
54748
|
+
hasUsageGuide: false,
|
|
54749
|
+
hasAPIReference: false
|
|
54750
|
+
},
|
|
54751
|
+
explanation: "Documentation assessment skipped"
|
|
54752
|
+
};
|
|
54753
|
+
}
|
|
54754
|
+
createEmptyErrorHandlingResult() {
|
|
54755
|
+
return {
|
|
54756
|
+
status: "PASS",
|
|
54757
|
+
recommendations: [],
|
|
54758
|
+
metrics: {
|
|
54759
|
+
mcpComplianceScore: 100,
|
|
54760
|
+
errorResponseQuality: "excellent",
|
|
54761
|
+
hasProperErrorCodes: true,
|
|
54762
|
+
hasDescriptiveMessages: true,
|
|
54763
|
+
validatesInputs: true
|
|
54764
|
+
},
|
|
54765
|
+
explanation: "Error handling assessment skipped"
|
|
54766
|
+
};
|
|
54767
|
+
}
|
|
54768
|
+
createEmptyUsabilityResult() {
|
|
54769
|
+
return {
|
|
54770
|
+
status: "PASS",
|
|
54771
|
+
recommendations: [],
|
|
54772
|
+
metrics: {
|
|
54773
|
+
toolNamingConvention: "consistent",
|
|
54774
|
+
parameterClarity: "clear",
|
|
54775
|
+
hasHelpfulDescriptions: true,
|
|
54776
|
+
followsBestPractices: true
|
|
54777
|
+
},
|
|
54778
|
+
explanation: "Usability assessment skipped"
|
|
54779
|
+
};
|
|
54780
|
+
}
|
|
54348
54781
|
}
|
|
54349
54782
|
const badgeVariants = cva(
|
|
54350
54783
|
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
@@ -58620,13 +59053,13 @@ const App = () => {
|
|
|
58620
59053
|
) });
|
|
58621
59054
|
if (window.location.pathname === "/oauth/callback") {
|
|
58622
59055
|
const OAuthCallback = React.lazy(
|
|
58623
|
-
() => __vitePreload(() => import("./OAuthCallback-
|
|
59056
|
+
() => __vitePreload(() => import("./OAuthCallback-BDIUPkR-.js"), true ? [] : void 0)
|
|
58624
59057
|
);
|
|
58625
59058
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
|
|
58626
59059
|
}
|
|
58627
59060
|
if (window.location.pathname === "/oauth/callback/debug") {
|
|
58628
59061
|
const OAuthDebugCallback = React.lazy(
|
|
58629
|
-
() => __vitePreload(() => import("./OAuthDebugCallback-
|
|
59062
|
+
() => __vitePreload(() => import("./OAuthDebugCallback-DPLV3zir.js"), true ? [] : void 0)
|
|
58630
59063
|
);
|
|
58631
59064
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
|
|
58632
59065
|
}
|
package/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/mcp.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>MCP Inspector</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DKTSB7VQ.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-32-uLPhe.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root" class="w-full"></div>
|