Skip to content

fix: accept cursor param in session.toolkits() pagination#3019

Open
zen-agent wants to merge 1 commit intonextfrom
zen/fix-toolkits-pagination-7w7got
Open

fix: accept cursor param in session.toolkits() pagination#3019
zen-agent wants to merge 1 commit intonextfrom
zen/fix-toolkits-pagination-7w7got

Conversation

@zen-agent
Copy link
Copy Markdown
Contributor

Description

Fix HIGH severity bug: session.toolkits() pagination is broken because the SDK's ToolRouterToolkitsOptionsSchema only accepts nextCursor as the cursor field name, but users naturally pass cursor (the standard pagination convention).

Root cause: Zod's safeParse silently strips unknown keys. When a user passes { cursor: "Mi0yMA==" }, Zod strips the cursor field (not in schema), leaving nextCursor as undefined. The API call then receives no cursor → always returns page 1.

Fix:

  • Added cursor as an accepted field in ToolRouterToolkitsOptionsSchema alongside nextCursor (backward compatible)
  • Updated the toolkits() method to use cursor first, falling back to nextCursor
  • cursor takes priority when both are provided

Files changed:

  • ts/packages/core/src/types/toolRouter.types.ts — Added cursor field to options schema
  • ts/packages/core/src/models/ToolRouterSession.ts — Use cursor ?? nextCursor for API call
  • ts/packages/core/test/models/toolRouter.test.ts — Added 3 new tests for cursor param

How did I test this PR

  • Ran vitest run test/models/toolRouter.test.ts — all 90 tests passed (including 3 new ones)
  • New test: cursor param is correctly forwarded to API
  • New test: cursor takes priority over nextCursor when both provided
  • Verified API endpoint directly works with pagination via curl against local Apollo:
    • Page 1: curl "localhost:9900/api/v3/tool_router/session/trs_xxx/toolkits?limit=5" → slugs: gmail, composio, github...
    • Page 2: curl "...?limit=5&cursor=Mi01" → slugs: googlesheets, slack, supabase... (different items confirmed)

Triggered by: soham@composio.dev | Source: slack
Session: https://zen-api-production-4c98.up.railway.app/dashboard/#/chat/zen-c34fbd50ad9d

The ToolRouterToolkitsOptionsSchema only accepted `nextCursor` as the
pagination cursor field name. Users naturally pass `cursor` (the standard
pagination convention), but Zod's safeParse silently strips unknown keys,
causing the cursor to always be undefined and every page returning page 1.

Add `cursor` as an accepted field alongside `nextCursor` (backward compat),
with `cursor` taking priority when both are provided.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@zen-agent zen-agent requested a review from haxzie as a code owner March 25, 2026 20:51
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Mar 25, 2026 8:51pm

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 25, 2026

⚠️ Security Audit Warning

The pnpm audit --prod check found security vulnerabilities in production dependencies.

Please review and fix the vulnerabilities. You can try running:

pnpm audit --fix --prod
Audit output
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ minimatch has a ReDoS via repeated wildcards with      │
│                     │ non-matching literal in pattern                        │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ minimatch                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=5.0.0 <5.1.7                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=5.1.7                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__packages__cli>openapi-typescript>@redocly/openapi- │
│                     │ core>minimatch                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-3ppc-4f35-3m26      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ minimatch has a ReDoS via repeated wildcards with      │
│                     │ non-matching literal in pattern                        │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ minimatch                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=9.0.0 <9.0.6                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=9.0.6                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__examples__google>@google/genai>google-auth-        │
│                     │ library>gaxios>rimraf>glob>minimatch                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-3ppc-4f35-3m26      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ minimatch has ReDoS: matchOne() combinatorial          │
│                     │ backtracking via multiple non-adjacent GLOBSTAR        │
│                     │ segments                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ minimatch                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=5.0.0 <5.1.8                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=5.1.8                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__packages__cli>openapi-typescript>@redocly/openapi- │
│                     │ core>minimatch                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-7r86-cg39-jmmj      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ minimatch has ReDoS: matchOne() combinatorial          │
│                     │ backtracking via multiple non-adjacent GLOBSTAR        │
│                     │ segments                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ minimatch                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=9.0.0 <9.0.7                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=9.0.7                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__examples__google>@google/genai>google-auth-        │
│                     │ library>gaxios>rimraf>glob>minimatch                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-7r86-cg39-jmmj      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ minimatch has ReDoS: matchOne() combinatorial          │
│                     │ backtracking via multiple non-adjacent GLOBSTAR        │
│                     │ segments                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ minimatch                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=10.0.0 <10.2.3                                       │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=10.2.3                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__packages__cli>@zed-industries/claude-code-         │
│                     │ acp>minimatch                                          │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-7r86-cg39-jmmj      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ minimatch ReDoS: nested *() extglobs generate          │
│                     │ catastrophically backtracking regular expressions      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ minimatch                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=5.0.0 <5.1.8                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=5.1.8                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__packages__cli>openapi-typescript>@redocly/openapi- │
│                     │ core>minimatch                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-23c5-xmqv-rm74      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ minimatch ReDoS: nested *() extglobs generate          │
│                     │ catastrophically backtracking regular expressions      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ minimatch                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=9.0.0 <9.0.7                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=9.0.7                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__examples__google>@google/genai>google-auth-        │
│                     │ library>gaxios>rimraf>glob>minimatch                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-23c5-xmqv-rm74      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ minimatch ReDoS: nested *() extglobs generate          │
│                     │ catastrophically backtracking regular expressions      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ minimatch                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=10.0.0 <10.2.3                                       │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=10.2.3                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__packages__cli>@zed-industries/claude-code-         │
│                     │ acp>minimatch                                          │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-23c5-xmqv-rm74      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ Hono vulnerable to arbitrary file access via           │
│                     │ serveStatic vulnerability                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.4                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.4                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__cloudflare__cf-workers-       │
│                     │ basic>hono                                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-q5qw-h33p-qvwr      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ @hono/node-server has authorization bypass for         │
│                     │ protected static paths via encoded slashes in Serve    │
│                     │ Static Middleware                                      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ @hono/node-server                                      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <1.19.10                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=1.19.10                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v3>@mastra/core>@modelcontextprotocol/sdk>@hono/node-  │
│                     │ server                                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-wc8c-qw6v-h7f6      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ express-rate-limit: IPv4-mapped IPv6 addresses bypass  │
│                     │ per-client rate limiting on servers with dual-stack    │
│                     │ network                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ express-rate-limit                                     │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=8.2.0 <8.2.2                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=8.2.2                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v3>@mastra/core>@modelcontextprotocol/sdk>express-     │
│                     │ rate-limit                                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-46wh-pxpv-q5gq      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ Effect `AsyncLocalStorage` context lost/contaminated   │
│                     │ inside Effect fibers under concurrent load with RPC    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ effect                                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <3.20.0                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=3.20.0                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__packages__cli>effect                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-38f7-945m-qr2g      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ Hono Vulnerable to Cookie Attribute Injection via      │
│                     │ Unsanitized domain and path in setCookie()             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.4                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.4                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__cloudflare__cf-workers-       │
│                     │ basic>hono                                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-5pq2-9x2x-5p6w      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ Hono Vulnerable to SSE Control Field Injection via     │
│                     │ CR/LF in writeSSE()                                    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.4                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.4                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__cloudflare__cf-workers-       │
│                     │ basic>hono                                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-p6xx-57qc-3wxr      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ Hono vulnerable to Prototype Pollution possible        │
│                     │ through __proto__ key allowed in parseBody({ dot: true │
│                     │ })                                                     │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.12.7                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.12.7                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__cloudflare__cf-workers-       │
│                     │ basic>hono                                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-v8w9-8mx6-g223      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ yaml is vulnerable to Stack Overflow via deeply nested │
│                     │ YAML collections                                       │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ yaml                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=2.0.0 <2.8.3                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=2.8.3                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__packages__cli>@effect/cli>yaml                     │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-48c2-rrv3-qjmp      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ low                 │ Hono added timing comparison hardening in basicAuth    │
│                     │ and bearerAuth                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ hono                                                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <4.11.10                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=4.11.10                                              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__cloudflare__cf-workers-       │
│                     │ basic>hono                                             │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-gq3j-xvxp-8hrf      │
└─────────────────────┴────────────────────────────────────────────────────────┘
17 vulnerabilities found
Severity: 1 low | 4 moderate | 12 high

@zen-agent
Copy link
Copy Markdown
Contributor Author

Post-PR Status Update

Build Checks

  • Typecheck: PASS
  • Build: PASS
  • Unit tests (90 tests): PASS

Codex Review

  • Result: LGTM — no actionable issues found
  • Iterations: 1

CI Status

  • 12/13 checks passed — Build, Typecheck, Audit, E2E (Node 20.18/20.19/22.12, Deno 2.6.7, CLI scratch, Cloudflare), Secrets, Vercel, Cursor Bugbot all green
  • 1 pre-existing failure: Test Typescript SDK — CLI help text assertions in projects.switch.cmd.test.ts and tools.execute.cmd.test.ts (unrelated to this PR, no files in ts/packages/cli/ were changed)

E2E Testing

  • Verified pagination works against local Apollo server:
    • Page 1: 20 items, first slug gmail, next_cursor: Mi0yMA==
    • Page 2 (with cursor): 20 different items, first slug tavily — confirms pagination param is correctly passed through

PR Comments

  • No comments or reviews to address

Summary

All post-PR tasks complete. The only CI failure is a pre-existing CLI test issue on main — completely unrelated to this pagination fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants