Skip to content

Refuse non-string plugin refs and Bot ids before the store - #487

Merged
davidmckayv merged 2 commits into
CopilotKit:mainfrom
Ayush7614:fix/plugins-grants-call-type-validation
Sep 11, 2026
Merged

Refuse non-string plugin refs and Bot ids before the store#487
davidmckayv merged 2 commits into
CopilotKit:mainfrom
Ayush7614:fix/plugins-grants-call-type-validation

Conversation

@Ayush7614

Copy link
Copy Markdown
Contributor

What this changes

POST /api/plugins/grants and POST /api/plugins/call checked presence (!body?.ref), not shape. The body is JSON, so {"ref":123,"agentId":[]} is truthy, passed the guard, and reached the store where Drizzle compares a text column against a number/object — a 500 instead of a 400, with no sentence naming what is required. Both routes now require non-empty strings (trimmed) for ref/agentId. Query-param DELETE /grants already deals in strings and is untouched.

Where it runs

  • New state that outlives a request? None. Request-shape check at the route edge.
  • What happens on the second replica? Same 400 on every replica: pure function of the request body.
  • Anything serialised? No. Refusal happens before grant/call/audit writes.
  • Anything fanned out to a browser? No.
  • New listener, port, or schedule? No.

Boundary and audit

  • Every acting call still goes through the gateway: resolve, decide, audit, then act. Grant/refusal/audit ordering inside the store is unchanged; only malformed input is stopped earlier.
  • New refusals and new failures each write a row. N/A by design: a 400 for malformed input writes no row, matching the existing missing-field path.
  • Nothing new is trusted from the client that the server can resolve itself. Stricter, not looser: fewer client shapes reach canUseBot, the grant store, and vendors.

Changelog

  • A line in CHANGELOG.md under Unreleased: non-string grant/call entry.

Proof

  • bun test server/tests/plugin-grants-validation.test.ts: 10 pass (number/object/array/whitespace refs and agentIds each 400 with the existing message, zero store calls).
  • bun run format:check: clean. bun run lint: clean.
  • Server typecheck passes (app has the pre-existing embla-carousel-react failure identical on clean main).

@davidmckayv davidmckayv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep-reviewed clean (validation, no secret leak, fail-closed, agrees with existing layers). CI green.

@davidmckayv
davidmckayv merged commit 5b61ca4 into CopilotKit:main Sep 11, 2026
15 checks passed
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