@bryan-thompson/inspector-assessment-client 1.15.0 → 1.15.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.
@@ -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-CPXmfP9b.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-BAbFakRL.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-CPXmfP9b.js";
1
+ import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-BAbFakRL.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.15.0";
16323
+ const version$1 = "1.15.1";
16324
16324
  const packageJson = {
16325
16325
  name,
16326
16326
  version: version$1
@@ -48863,7 +48863,7 @@ const useTheme = () => {
48863
48863
  [theme, setThemeWithSideEffect]
48864
48864
  );
48865
48865
  };
48866
- const version = "1.15.0";
48866
+ const version = "1.15.1";
48867
48867
  var [createTooltipContext] = createContextScope("Tooltip", [
48868
48868
  createPopperScope
48869
48869
  ]);
@@ -61877,13 +61877,13 @@ const App = () => {
61877
61877
  ) });
61878
61878
  if (window.location.pathname === "/oauth/callback") {
61879
61879
  const OAuthCallback = React.lazy(
61880
- () => __vitePreload(() => import("./OAuthCallback-BleN4Jjs.js"), true ? [] : void 0)
61880
+ () => __vitePreload(() => import("./OAuthCallback-tZBHqkSF.js"), true ? [] : void 0)
61881
61881
  );
61882
61882
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
61883
61883
  }
61884
61884
  if (window.location.pathname === "/oauth/callback/debug") {
61885
61885
  const OAuthDebugCallback = React.lazy(
61886
- () => __vitePreload(() => import("./OAuthDebugCallback-C__lzEyx.js"), true ? [] : void 0)
61886
+ () => __vitePreload(() => import("./OAuthDebugCallback-D73S8G8X.js"), true ? [] : void 0)
61887
61887
  );
61888
61888
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
61889
61889
  }
package/dist/index.html CHANGED
@@ -5,7 +5,7 @@
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-CPXmfP9b.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-BAbFakRL.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-BdXNC65t.css">
10
10
  </head>
11
11
  <body>
@@ -12,6 +12,7 @@ import { BaseAssessor } from "./BaseAssessor.js";
12
12
  export declare class TemporalAssessor extends BaseAssessor {
13
13
  private invocationsPerTool;
14
14
  private readonly DESTRUCTIVE_PATTERNS;
15
+ private readonly PER_INVOCATION_TIMEOUT;
15
16
  constructor(config: AssessmentConfiguration);
16
17
  assess(context: AssessmentContext): Promise<TemporalAssessment>;
17
18
  private assessTool;
@@ -1 +1 @@
1
- {"version":3,"file":"TemporalAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/TemporalAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,uBAAuB,EAEvB,kBAAkB,EAEnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAS9C,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,kBAAkB,CAAS;IAGnC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAanC;gBAEU,MAAM,EAAE,uBAAuB;IAKrC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YA8CvD,UAAU;IA8CxB,OAAO,CAAC,gBAAgB;IA0DxB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAsC3B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IA0CzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,uBAAuB;CA8BhC"}
1
+ {"version":3,"file":"TemporalAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/TemporalAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,uBAAuB,EAEvB,kBAAkB,EAEnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAY9C,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,kBAAkB,CAAS;IAGnC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAoBnC;IAGF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAU;gBAErC,MAAM,EAAE,uBAAuB;IAKrC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YA8CvD,UAAU;IAkExB,OAAO,CAAC,gBAAgB;IA0DxB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAsC3B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAoDzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,uBAAuB;CA8BhC"}
@@ -7,6 +7,8 @@
7
7
  * payloads but never call the same tool repeatedly with identical payloads.
8
8
  */
9
9
  import { BaseAssessor } from "./BaseAssessor.js";
10
+ // Security: Maximum response size to prevent memory exhaustion attacks
11
+ const MAX_RESPONSE_SIZE = 1_000_000; // 1MB
10
12
  export class TemporalAssessor extends BaseAssessor {
11
13
  invocationsPerTool;
12
14
  // Patterns that suggest a tool may have side effects
@@ -23,7 +25,16 @@ export class TemporalAssessor extends BaseAssessor {
23
25
  "submit",
24
26
  "execute",
25
27
  "run",
28
+ // P2-3: Additional destructive patterns
29
+ "drop",
30
+ "truncate",
31
+ "clear",
32
+ "purge",
33
+ "destroy",
34
+ "reset",
26
35
  ];
36
+ // P2-2: Per-invocation timeout to prevent long-running tools from blocking
37
+ PER_INVOCATION_TIMEOUT = 10_000; // 10 seconds
27
38
  constructor(config) {
28
39
  super(config);
29
40
  this.invocationsPerTool = config.temporalInvocations ?? 25;
@@ -72,7 +83,19 @@ export class TemporalAssessor extends BaseAssessor {
72
83
  for (let i = 1; i <= invocations; i++) {
73
84
  this.testCount++;
74
85
  try {
75
- const response = await this.executeWithTimeout(context.callTool(tool.name, payload));
86
+ // P2-2: Use shorter per-invocation timeout (10s vs default 30s)
87
+ const response = await this.executeWithTimeout(context.callTool(tool.name, payload), this.PER_INVOCATION_TIMEOUT);
88
+ // Security: Prevent memory exhaustion from large responses
89
+ const responseSize = JSON.stringify(response).length;
90
+ if (responseSize > MAX_RESPONSE_SIZE) {
91
+ responses.push({
92
+ invocation: i,
93
+ response: null,
94
+ error: `Response exceeded size limit (${responseSize} > ${MAX_RESPONSE_SIZE} bytes)`,
95
+ timestamp: Date.now(),
96
+ });
97
+ continue;
98
+ }
76
99
  responses.push({
77
100
  invocation: i,
78
101
  response,
@@ -88,6 +111,10 @@ export class TemporalAssessor extends BaseAssessor {
88
111
  timestamp: Date.now(),
89
112
  });
90
113
  }
114
+ // P2-4: Small delay between invocations to prevent rate limiting false positives
115
+ if (i < invocations) {
116
+ await this.sleep(50);
117
+ }
91
118
  }
92
119
  const result = this.analyzeResponses(tool, responses);
93
120
  return {
@@ -191,8 +218,8 @@ export class TemporalAssessor extends BaseAssessor {
191
218
  normalizeResponse(response) {
192
219
  const str = JSON.stringify(response);
193
220
  return (str
194
- // ISO timestamps
195
- .replace(/"\d{4}-\d{2}-\d{2}T[\d:.]+Z?"/g, '"<TIMESTAMP>"')
221
+ // ISO timestamps (bounded quantifier to prevent ReDoS)
222
+ .replace(/"\d{4}-\d{2}-\d{2}T[\d:.]{1,30}Z?"/g, '"<TIMESTAMP>"')
196
223
  // Unix timestamps (13 digits)
197
224
  .replace(/"\d{13}"/g, '"<TIMESTAMP>"')
198
225
  // UUIDs
@@ -218,7 +245,11 @@ export class TemporalAssessor extends BaseAssessor {
218
245
  .replace(/"index":\s*\d+/g, '"index": <NUMBER>')
219
246
  .replace(/\\"index\\":\s*\d+/g, '\\"index\\": <NUMBER>')
220
247
  // String IDs
221
- .replace(/"id":\s*"[^"]+"/g, '"id": "<ID>"'));
248
+ .replace(/"id":\s*"[^"]+"/g, '"id": "<ID>"')
249
+ // P2-1: Additional timestamp fields that vary between calls
250
+ .replace(/"(updated_at|created_at|modified_at)":\s*"[^"]+"/g, '"$1": "<TIMESTAMP>"')
251
+ // P2-1: Dynamic tokens/hashes that change per request
252
+ .replace(/"(nonce|token|hash|etag|session_id|correlation_id)":\s*"[^"]+"/g, '"$1": "<DYNAMIC>"'));
222
253
  }
223
254
  /**
224
255
  * Detect if a tool may have side effects based on naming patterns.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bryan-thompson/inspector-assessment-client",
3
- "version": "1.15.0",
3
+ "version": "1.15.1",
4
4
  "description": "Client-side application for the Enhanced MCP Inspector with assessment capabilities",
5
5
  "license": "MIT",
6
6
  "author": "Bryan Thompson <bryan@triepod.ai>",