@bryan-thompson/inspector-assessment 1.1.0 → 1.2.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.
@@ -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-DrU0QB6A.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-CkSRacMw.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-DrU0QB6A.js";
1
+ import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-CkSRacMw.js";
2
2
  const OAuthDebugCallback = ({ onConnect }) => {
3
3
  reactExports.useEffect(() => {
4
4
  let isProcessed = false;
@@ -1332,6 +1332,9 @@ video {
1332
1332
  .whitespace-nowrap {
1333
1333
  white-space: nowrap;
1334
1334
  }
1335
+ .whitespace-pre-line {
1336
+ white-space: pre-line;
1337
+ }
1335
1338
  .whitespace-pre-wrap {
1336
1339
  white-space: pre-wrap;
1337
1340
  }
@@ -1383,6 +1386,10 @@ video {
1383
1386
  .border-t {
1384
1387
  border-top-width: 1px;
1385
1388
  }
1389
+ .border-amber-500 {
1390
+ --tw-border-opacity: 1;
1391
+ border-color: rgb(245 158 11 / var(--tw-border-opacity, 1));
1392
+ }
1386
1393
  .border-blue-200 {
1387
1394
  --tw-border-opacity: 1;
1388
1395
  border-color: rgb(191 219 254 / var(--tw-border-opacity, 1));
@@ -1474,6 +1481,14 @@ video {
1474
1481
  .bg-accent {
1475
1482
  background-color: hsl(var(--accent));
1476
1483
  }
1484
+ .bg-amber-100 {
1485
+ --tw-bg-opacity: 1;
1486
+ background-color: rgb(254 243 199 / var(--tw-bg-opacity, 1));
1487
+ }
1488
+ .bg-amber-50 {
1489
+ --tw-bg-opacity: 1;
1490
+ background-color: rgb(255 251 235 / var(--tw-bg-opacity, 1));
1491
+ }
1477
1492
  .bg-background {
1478
1493
  background-color: hsl(var(--background));
1479
1494
  }
@@ -1550,6 +1565,10 @@ video {
1550
1565
  .bg-muted\/50 {
1551
1566
  background-color: hsl(var(--muted) / 0.5);
1552
1567
  }
1568
+ .bg-orange-100 {
1569
+ --tw-bg-opacity: 1;
1570
+ background-color: rgb(255 237 213 / var(--tw-bg-opacity, 1));
1571
+ }
1553
1572
  .bg-orange-50 {
1554
1573
  --tw-bg-opacity: 1;
1555
1574
  background-color: rgb(255 247 237 / var(--tw-bg-opacity, 1));
@@ -1818,6 +1837,14 @@ video {
1818
1837
  --tw-text-opacity: 1;
1819
1838
  color: rgb(217 119 6 / var(--tw-text-opacity, 1));
1820
1839
  }
1840
+ .text-amber-800 {
1841
+ --tw-text-opacity: 1;
1842
+ color: rgb(146 64 14 / var(--tw-text-opacity, 1));
1843
+ }
1844
+ .text-amber-900 {
1845
+ --tw-text-opacity: 1;
1846
+ color: rgb(120 53 15 / var(--tw-text-opacity, 1));
1847
+ }
1821
1848
  .text-blue-500 {
1822
1849
  --tw-text-opacity: 1;
1823
1850
  color: rgb(59 130 246 / var(--tw-text-opacity, 1));
@@ -1912,6 +1939,10 @@ video {
1912
1939
  --tw-text-opacity: 1;
1913
1940
  color: rgb(234 88 12 / var(--tw-text-opacity, 1));
1914
1941
  }
1942
+ .text-orange-800 {
1943
+ --tw-text-opacity: 1;
1944
+ color: rgb(154 52 18 / var(--tw-text-opacity, 1));
1945
+ }
1915
1946
  .text-popover-foreground {
1916
1947
  color: hsl(var(--popover-foreground));
1917
1948
  }
@@ -16205,7 +16205,7 @@ objectType({
16205
16205
  token_type_hint: stringType().optional()
16206
16206
  }).strip();
16207
16207
  const name = "@bryan-thompson/inspector-assessment-client";
16208
- const version$1 = "1.1.0";
16208
+ const version$1 = "1.2.0";
16209
16209
  const packageJson = {
16210
16210
  name,
16211
16211
  version: version$1
@@ -41736,7 +41736,7 @@ const useTheme = () => {
41736
41736
  [theme, setThemeWithSideEffect]
41737
41737
  );
41738
41738
  };
41739
- const version = "1.1.0";
41739
+ const version = "1.2.0";
41740
41740
  var [createTooltipContext] = createContextScope("Tooltip", [
41741
41741
  createPopperScope
41742
41742
  ]);
@@ -46378,6 +46378,13 @@ class SecurityAssessor extends BaseAssessor {
46378
46378
  response,
46379
46379
  payload
46380
46380
  );
46381
+ const confidenceResult = this.calculateConfidence(
46382
+ tool,
46383
+ isVulnerable,
46384
+ evidence || "",
46385
+ this.extractResponseContent(response),
46386
+ payload
46387
+ );
46381
46388
  return {
46382
46389
  testName: attackName,
46383
46390
  description: payload.description,
@@ -46386,7 +46393,8 @@ class SecurityAssessor extends BaseAssessor {
46386
46393
  toolName: tool.name,
46387
46394
  vulnerable: isVulnerable,
46388
46395
  evidence,
46389
- response: this.extractResponseContent(response)
46396
+ response: this.extractResponseContent(response),
46397
+ ...confidenceResult
46390
46398
  };
46391
46399
  } catch (error) {
46392
46400
  return {
@@ -46521,6 +46529,95 @@ class SecurityAssessor extends BaseAssessor {
46521
46529
  ).length;
46522
46530
  return `Found ${vulnCount} vulnerabilities (${criticalCount} critical, ${moderateCount} moderate) across ${testCount} security tests. Risk level: ${riskLevel}. Tools may execute malicious commands or leak sensitive data.`;
46523
46531
  }
46532
+ /**
46533
+ * Calculate confidence level and manual review requirements
46534
+ * Detects ambiguous patterns that need human verification
46535
+ */
46536
+ calculateConfidence(tool, isVulnerable, evidence, responseText, payload) {
46537
+ var _a;
46538
+ const toolDescription = (tool.description || "").toLowerCase();
46539
+ const toolName = tool.name.toLowerCase();
46540
+ const responseLower = responseText.toLowerCase();
46541
+ const payloadLower = payload.payload.toLowerCase();
46542
+ if (!isVulnerable && (evidence.includes("safely reflected") || evidence.includes("API wrapper") || evidence.includes("safe: true"))) {
46543
+ return {
46544
+ confidence: "high",
46545
+ requiresManualReview: false
46546
+ };
46547
+ }
46548
+ if (isVulnerable && evidence.includes("executed") && !this.isStructuredDataTool(toolName, toolDescription)) {
46549
+ return {
46550
+ confidence: "high",
46551
+ requiresManualReview: false
46552
+ };
46553
+ }
46554
+ if (isVulnerable) {
46555
+ const isDataTool = this.isStructuredDataTool(toolName, toolDescription);
46556
+ const hasStructuredData = /title:|name:|description:|trust score:|id:|snippets:/i.test(
46557
+ responseText
46558
+ ) || /^\s*-\s+/m.test(responseText) || // Bullet points
46559
+ /"[^"]+"\s*:\s*"[^"]+"/g.test(responseText);
46560
+ const patternInInput = (_a = payload.evidence) == null ? void 0 : _a.test(payloadLower);
46561
+ const echosInput = responseLower.includes(payloadLower);
46562
+ if (isDataTool && (hasStructuredData || echosInput) && patternInInput) {
46563
+ return {
46564
+ confidence: "low",
46565
+ requiresManualReview: true,
46566
+ manualReviewReason: "Pattern matched in structured data response. Tool may be legitimately returning data containing search terms rather than executing malicious code.",
46567
+ reviewGuidance: `Verify: 1) Does the tool actually execute/compute the input? 2) Or does it just return pre-existing data that happens to contain the pattern? 3) Check if '${payload.evidence}' appears in legitimate tool output vs. execution results.`
46568
+ };
46569
+ }
46570
+ if (payload.evidence && /\b\d\b/.test(payload.evidence.toString()) && /\b(score|count|trust|rating|id|version)\b/i.test(responseText)) {
46571
+ return {
46572
+ confidence: "low",
46573
+ requiresManualReview: true,
46574
+ manualReviewReason: "Numeric pattern found in response with numeric metadata (scores, counts, etc.). May be coincidental data rather than arithmetic execution.",
46575
+ reviewGuidance: "Verify: 1) Did the tool actually compute an arithmetic result? 2) Or does the number appear in metadata like trust scores, version numbers, or counts? 3) Compare pattern location in response with tool's expected output format."
46576
+ };
46577
+ }
46578
+ if (/admin|role|privilege|elevated/i.test(payload.payload) && /\b(library|search|documentation|api|wrapper)\b/i.test(toolDescription)) {
46579
+ return {
46580
+ confidence: "low",
46581
+ requiresManualReview: true,
46582
+ manualReviewReason: "Admin-related keywords found in search/retrieval tool results. Tool may be returning data about admin-related libraries/APIs rather than elevating privileges.",
46583
+ reviewGuidance: "Verify: 1) Did the tool actually change behavior or assume admin role? 2) Or did it return search results for admin-related content? 3) Test if tool behavior actually changed after this request."
46584
+ };
46585
+ }
46586
+ }
46587
+ if (isVulnerable && evidence.includes("executed")) {
46588
+ return {
46589
+ confidence: "medium",
46590
+ requiresManualReview: true,
46591
+ manualReviewReason: "Execution indicators found but context suggests possible ambiguity.",
46592
+ reviewGuidance: "Verify: 1) Review the full response to confirm actual code execution. 2) Check if tool's intended function involves execution. 3) Test with variations to confirm consistency."
46593
+ };
46594
+ }
46595
+ return {
46596
+ confidence: "high",
46597
+ requiresManualReview: false
46598
+ };
46599
+ }
46600
+ /**
46601
+ * Check if tool is a structured data tool (search, lookup, retrieval)
46602
+ * These tools naturally echo input patterns in their results
46603
+ */
46604
+ isStructuredDataTool(toolName, toolDescription) {
46605
+ const dataToolPatterns = [
46606
+ /search/i,
46607
+ /find/i,
46608
+ /lookup/i,
46609
+ /query/i,
46610
+ /retrieve/i,
46611
+ /fetch/i,
46612
+ /get/i,
46613
+ /list/i,
46614
+ /resolve/i,
46615
+ /discover/i,
46616
+ /browse/i
46617
+ ];
46618
+ const combined = `${toolName} ${toolDescription}`;
46619
+ return dataToolPatterns.some((pattern2) => pattern2.test(combined));
46620
+ }
46524
46621
  /**
46525
46622
  * Check if response is just reflection (safe)
46526
46623
  * Expanded to catch more reflection patterns including echo, repeat, display
@@ -49778,11 +49875,11 @@ const ReviewerAssessmentView = ({
49778
49875
  {
49779
49876
  id: "documentation",
49780
49877
  name: "3. Documentation Quality",
49781
- quickCheck: `${assessment.documentation.metrics.hasReadme ? "Has README" : "Missing README"}, ${assessment.documentation.metrics.exampleCount} examples`,
49878
+ quickCheck: `${assessment.documentation.metrics.hasReadme ? "Has README" : "Missing README"}, ${assessment.documentation.metrics.exampleCount} functional examples found`,
49782
49879
  verdict: assessment.documentation.status === "PASS" ? "PASS" : assessment.documentation.metrics.exampleCount < 3 ? "FAIL" : "REVIEW_NEEDED",
49783
49880
  evidence: [
49784
49881
  `Has README: ${assessment.documentation.metrics.hasReadme ? "Yes" : "No"}`,
49785
- `Code examples: ${assessment.documentation.metrics.exampleCount} (need 3+)`,
49882
+ `Functional examples: ${assessment.documentation.metrics.exampleCount} found (3+ required)`,
49786
49883
  `Has installation instructions: ${assessment.documentation.metrics.hasInstallInstructions ? "Yes" : "No"}`,
49787
49884
  `Has usage guide: ${assessment.documentation.metrics.hasUsageGuide ? "Yes" : "No"}`
49788
49885
  ],
@@ -51126,9 +51223,7 @@ const AssessmentTab = ({
51126
51223
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
51127
51224
  "Examples:",
51128
51225
  " ",
51129
- assessment.documentation.metrics.exampleCount,
51130
- "/",
51131
- assessment.documentation.metrics.requiredExamples
51226
+ assessment.documentation.metrics.exampleCount >= assessment.documentation.metrics.requiredExamples ? `${assessment.documentation.metrics.exampleCount} found (${assessment.documentation.metrics.requiredExamples}+ required) ✓` : `${assessment.documentation.metrics.exampleCount}/${assessment.documentation.metrics.requiredExamples} (need more)`
51132
51227
  ] }),
51133
51228
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
51134
51229
  "Install Guide:",
@@ -52165,9 +52260,30 @@ const SecurityVulnerabilityItem = ({ testResult, toolName }) => {
52165
52260
  testResult.vulnerable ? "🚨 VULNERABLE - Tool executed malicious input!" : "✅ SECURE - Tool properly rejected malicious input"
52166
52261
  ]
52167
52262
  }
52168
- )
52263
+ ),
52264
+ testResult.confidence && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
52265
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Confidence:" }),
52266
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
52267
+ "span",
52268
+ {
52269
+ className: `text-xs px-2 py-1 rounded font-semibold ${testResult.confidence === "high" ? "bg-green-100 text-green-800" : testResult.confidence === "medium" ? "bg-yellow-100 text-yellow-800" : "bg-orange-100 text-orange-800"}`,
52270
+ children: testResult.confidence.toUpperCase()
52271
+ }
52272
+ )
52273
+ ] })
52169
52274
  ] })
52170
52275
  ] }),
52276
+ testResult.requiresManualReview && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-amber-50 border-l-4 border-amber-500 p-3 rounded", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2", children: [
52277
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5" }),
52278
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
52279
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold text-amber-900 mb-1", children: "⚠️ Manual Review Required" }),
52280
+ testResult.manualReviewReason && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-amber-800 mb-2", children: testResult.manualReviewReason }),
52281
+ testResult.reviewGuidance && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-amber-100 p-2 rounded text-xs text-amber-900", children: [
52282
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Review Steps:" }),
52283
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 whitespace-pre-line", children: testResult.reviewGuidance })
52284
+ ] })
52285
+ ] })
52286
+ ] }) }),
52171
52287
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
52172
52288
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1", children: "Test Payload" }),
52173
52289
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-black text-green-400 p-2 rounded text-xs font-mono whitespace-pre-wrap break-all", children: testResult.payload })
@@ -52328,7 +52444,7 @@ const generateTextReport = (assessment, filteredStatus, categoryFilter) => {
52328
52444
  `Status: ${assessment.documentation.status}`,
52329
52445
  assessment.documentation.explanation,
52330
52446
  `- Has README: ${assessment.documentation.metrics.hasReadme ? "Yes" : "No"}`,
52331
- `- Examples: ${assessment.documentation.metrics.exampleCount}/${assessment.documentation.metrics.requiredExamples}`,
52447
+ `- Examples: ${assessment.documentation.metrics.exampleCount} functional examples found (${assessment.documentation.metrics.requiredExamples}+ required)`,
52332
52448
  `- Installation Guide: ${assessment.documentation.metrics.hasInstallInstructions ? "Yes" : "No"}`,
52333
52449
  `- Usage Guide: ${assessment.documentation.metrics.hasUsageGuide ? "Yes" : "No"}`
52334
52450
  );
@@ -53165,13 +53281,13 @@ const App = () => {
53165
53281
  ) });
53166
53282
  if (window.location.pathname === "/oauth/callback") {
53167
53283
  const OAuthCallback = React.lazy(
53168
- () => __vitePreload(() => import("./OAuthCallback-aV2t2Zmo.js"), true ? [] : void 0)
53284
+ () => __vitePreload(() => import("./OAuthCallback-CS0hHvzr.js"), true ? [] : void 0)
53169
53285
  );
53170
53286
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
53171
53287
  }
53172
53288
  if (window.location.pathname === "/oauth/callback/debug") {
53173
53289
  const OAuthDebugCallback = React.lazy(
53174
- () => __vitePreload(() => import("./OAuthDebugCallback-Ca01948b.js"), true ? [] : void 0)
53290
+ () => __vitePreload(() => import("./OAuthDebugCallback-CRsLrDJk.js"), true ? [] : void 0)
53175
53291
  );
53176
53292
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
53177
53293
  }
@@ -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-DrU0QB6A.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-DYiWOife.css">
8
+ <script type="module" crossorigin src="/assets/index-CkSRacMw.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-Bc4MVSgQ.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root" class="w-full"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bryan-thompson/inspector-assessment",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Enhanced MCP Inspector with comprehensive assessment capabilities for server validation",
5
5
  "license": "MIT",
6
6
  "author": "Bryan Thompson <bryan@triepod.ai>",