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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/assets/{OAuthCallback-DhwTOA1q.js → OAuthCallback-D_dKq_wM.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-DzopkA29.js → OAuthDebugCallback-UqARwe_4.js} +1 -1
  3. package/dist/assets/{index-CzoGuYPy.css → index-32-uLPhe.css} +3 -0
  4. package/dist/assets/{index-zBRaltBB.js → index-B5_VY0TC.js} +458 -17
  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 +47 -8
  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
@@ -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-zBRaltBB.js";
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-B5_VY0TC.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-zBRaltBB.js";
1
+ import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-B5_VY0TC.js";
2
2
  const OAuthDebugCallback = ({ onConnect }) => {
3
3
  reactExports.useEffect(() => {
4
4
  let isProcessed = false;
@@ -850,6 +850,9 @@ video {
850
850
  .top-\[50\%\] {
851
851
  top: 50%;
852
852
  }
853
+ .isolate {
854
+ isolation: isolate;
855
+ }
853
856
  .z-10 {
854
857
  z-index: 10;
855
858
  }
@@ -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.18.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.18.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
- evidence: /(bearer|jwt|token|auth).*[a-zA-Z0-9-_]{20,}|eyJ[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+/i,
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
- evidence: /eyJ[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+/,
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);
@@ -53332,10 +53676,14 @@ class SecurityAssessor extends BaseAssessor {
53332
53676
  /action\s+received:/i,
53333
53677
  /input\s+received:/i,
53334
53678
  /request\s+received:/i,
53335
- // Explicit safety indicators in JSON responses
53336
- /"safe":\s*true/i,
53337
- /"vulnerable":\s*false/i,
53338
- /"status":\s*"acknowledged"/i
53679
+ // Explicit safety indicators in JSON responses (context-aware to avoid matching unrelated fields)
53680
+ // Require safety-related context: message, result, status, stored, reflected, etc.
53681
+ /"safe"\s*:\s*true[^}]*("message"|"result"|"status"|"response")/i,
53682
+ /("message"|"result"|"status"|"response")[^}]*"safe"\s*:\s*true/i,
53683
+ /"vulnerable"\s*:\s*false[^}]*("safe"|"stored"|"reflected"|"status")/i,
53684
+ /("safe"|"stored"|"reflected"|"status")[^}]*"vulnerable"\s*:\s*false/i,
53685
+ /"status"\s*:\s*"acknowledged"[^}]*("message"|"result"|"safe")/i,
53686
+ /("message"|"result"|"safe")[^}]*"status"\s*:\s*"acknowledged"/i
53339
53687
  ];
53340
53688
  const reflectionPatterns = [
53341
53689
  ...statusPatterns,
@@ -53576,7 +53924,33 @@ class SecurityAssessor extends BaseAssessor {
53576
53924
  const params = {};
53577
53925
  const targetParamTypes = payload.parameterTypes || [];
53578
53926
  let payloadInjected = false;
53579
- if (targetParamTypes.length > 0) {
53927
+ for (const [key, prop] of Object.entries(schema.properties)) {
53928
+ const propSchema = prop;
53929
+ if (propSchema.type !== "string") continue;
53930
+ const detectedLanguage = this.languageGenerator.detectLanguage(
53931
+ key,
53932
+ tool.name,
53933
+ tool.description
53934
+ );
53935
+ if (detectedLanguage !== "generic" && !payloadInjected) {
53936
+ const languagePayloads = this.languageGenerator.getPayloadsForLanguage(detectedLanguage);
53937
+ if (languagePayloads.length > 0) {
53938
+ const payloadLower = payload.payload.toLowerCase();
53939
+ const isCommandTest = payloadLower.includes("whoami") || payloadLower.includes("passwd") || payloadLower.includes("id");
53940
+ let selectedPayload = languagePayloads[0];
53941
+ if (isCommandTest) {
53942
+ const cmdPayload = languagePayloads.find(
53943
+ (lp) => lp.payload.includes("whoami") || lp.payload.includes("subprocess") || lp.payload.includes("execSync")
53944
+ );
53945
+ if (cmdPayload) selectedPayload = cmdPayload;
53946
+ }
53947
+ params[key] = selectedPayload.payload;
53948
+ payloadInjected = true;
53949
+ break;
53950
+ }
53951
+ }
53952
+ }
53953
+ if (!payloadInjected && targetParamTypes.length > 0) {
53580
53954
  for (const [key, prop] of Object.entries(schema.properties)) {
53581
53955
  const propSchema = prop;
53582
53956
  const paramNameLower = key.toLowerCase();
@@ -53586,7 +53960,8 @@ class SecurityAssessor extends BaseAssessor {
53586
53960
  break;
53587
53961
  }
53588
53962
  }
53589
- } else {
53963
+ }
53964
+ if (!payloadInjected) {
53590
53965
  for (const [key, prop] of Object.entries(schema.properties)) {
53591
53966
  const propSchema = prop;
53592
53967
  if (propSchema.type === "string" && !payloadInjected) {
@@ -53718,14 +54093,15 @@ class MCPAssessmentService {
53718
54093
  packageLock: void 0,
53719
54094
  privacyPolicy: void 0
53720
54095
  };
54096
+ const categories = this.config.assessmentCategories;
53721
54097
  const functionalityAssessor = new FunctionalityAssessor(this.config);
53722
- const functionality = await functionalityAssessor.assess(context);
54098
+ const functionality = categories?.functionality !== false ? await functionalityAssessor.assess(context) : this.createEmptyFunctionalityResult();
53723
54099
  const securityAssessor = new SecurityAssessor(this.config);
53724
- const security = await securityAssessor.assess(context);
53725
- const documentation = this.assessDocumentation(readmeContent || "", tools);
54100
+ const security = categories?.security !== false ? await securityAssessor.assess(context) : this.createEmptySecurityResult();
54101
+ const documentation = categories?.documentation !== false ? this.assessDocumentation(readmeContent || "", tools) : this.createEmptyDocumentationResult();
53726
54102
  const errorHandlingAssessor = new ErrorHandlingAssessor(this.config);
53727
- const errorHandling = await errorHandlingAssessor.assess(context);
53728
- const usability = this.assessUsability(tools);
54103
+ const errorHandling = categories?.errorHandling !== false ? await errorHandlingAssessor.assess(context) : this.createEmptyErrorHandlingResult();
54104
+ const usability = categories?.usability !== false ? this.assessUsability(tools) : this.createEmptyUsabilityResult();
53729
54105
  let mcpSpecCompliance;
53730
54106
  let mcpAssessor;
53731
54107
  if (this.config.enableExtendedAssessment) {
@@ -54345,6 +54721,71 @@ class MCPAssessmentService {
54345
54721
  }
54346
54722
  return recommendations;
54347
54723
  }
54724
+ // Helper methods for creating empty results when assessments are disabled
54725
+ createEmptyFunctionalityResult() {
54726
+ return {
54727
+ totalTools: 0,
54728
+ testedTools: 0,
54729
+ workingTools: 0,
54730
+ brokenTools: [],
54731
+ coveragePercentage: 100,
54732
+ status: "PASS",
54733
+ explanation: "Functionality assessment skipped",
54734
+ toolResults: []
54735
+ };
54736
+ }
54737
+ createEmptySecurityResult() {
54738
+ return {
54739
+ promptInjectionTests: [],
54740
+ vulnerabilities: [],
54741
+ overallRiskLevel: "LOW",
54742
+ status: "PASS",
54743
+ explanation: "Security assessment skipped"
54744
+ };
54745
+ }
54746
+ createEmptyDocumentationResult() {
54747
+ return {
54748
+ status: "PASS",
54749
+ recommendations: [],
54750
+ metrics: {
54751
+ hasReadme: false,
54752
+ exampleCount: 0,
54753
+ requiredExamples: 3,
54754
+ missingExamples: [],
54755
+ hasInstallInstructions: false,
54756
+ hasUsageGuide: false,
54757
+ hasAPIReference: false
54758
+ },
54759
+ explanation: "Documentation assessment skipped"
54760
+ };
54761
+ }
54762
+ createEmptyErrorHandlingResult() {
54763
+ return {
54764
+ status: "PASS",
54765
+ recommendations: [],
54766
+ metrics: {
54767
+ mcpComplianceScore: 100,
54768
+ errorResponseQuality: "excellent",
54769
+ hasProperErrorCodes: true,
54770
+ hasDescriptiveMessages: true,
54771
+ validatesInputs: true
54772
+ },
54773
+ explanation: "Error handling assessment skipped"
54774
+ };
54775
+ }
54776
+ createEmptyUsabilityResult() {
54777
+ return {
54778
+ status: "PASS",
54779
+ recommendations: [],
54780
+ metrics: {
54781
+ toolNamingConvention: "consistent",
54782
+ parameterClarity: "clear",
54783
+ hasHelpfulDescriptions: true,
54784
+ followsBestPractices: true
54785
+ },
54786
+ explanation: "Usability assessment skipped"
54787
+ };
54788
+ }
54348
54789
  }
54349
54790
  const badgeVariants = cva(
54350
54791
  "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 +59061,13 @@ const App = () => {
58620
59061
  ) });
58621
59062
  if (window.location.pathname === "/oauth/callback") {
58622
59063
  const OAuthCallback = React.lazy(
58623
- () => __vitePreload(() => import("./OAuthCallback-DhwTOA1q.js"), true ? [] : void 0)
59064
+ () => __vitePreload(() => import("./OAuthCallback-D_dKq_wM.js"), true ? [] : void 0)
58624
59065
  );
58625
59066
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
58626
59067
  }
58627
59068
  if (window.location.pathname === "/oauth/callback/debug") {
58628
59069
  const OAuthDebugCallback = React.lazy(
58629
- () => __vitePreload(() => import("./OAuthDebugCallback-DzopkA29.js"), true ? [] : void 0)
59070
+ () => __vitePreload(() => import("./OAuthDebugCallback-UqARwe_4.js"), true ? [] : void 0)
58630
59071
  );
58631
59072
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
58632
59073
  }
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-zBRaltBB.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-CzoGuYPy.css">
8
+ <script type="module" crossorigin src="/assets/index-B5_VY0TC.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>