Skip to content

Comments

fix(codemode): validate tool arguments against Zod schema before execution#962

Open
tumberger wants to merge 1 commit intocloudflare:mainfrom
tumberger:security/codemode-validate-tool-args
Open

fix(codemode): validate tool arguments against Zod schema before execution#962
tumberger wants to merge 1 commit intocloudflare:mainfrom
tumberger:security/codemode-validate-tool-args

Conversation

@tumberger
Copy link

@tumberger tumberger commented Feb 21, 2026

Summary

  • createCodeTool() extracts .execute functions from tools but discards their Zod schemas, passing them unwrapped to ToolDispatcher
  • ToolDispatcher.call() does JSON.parse(argsJson) → fn(args) with no schema validation, so sandboxed code can invoke tool functions with arbitrary JSON payloads that bypass the constraints defined by tool authors
  • This patch wraps each extracted execute function with its corresponding Zod schema (inputSchema or parameters) so arguments are validated before reaching the tool function — invalid payloads throw a ZodError caught by the existing error handler

Root cause

In tool.ts:101-111 (before this patch):

for (const [name, t] of Object.entries(tools)) {
  const execute = "execute" in t
    ? (t.execute as (args: unknown) => Promise<unknown>)
    : undefined;
  if (execute) {
    fns[sanitizeToolName(name)] = execute; // ← schema discarded
  }
}

The Zod schemas (t.inputSchema / t.parameters) are available but never extracted. When the sandbox calls a tool via ToolDispatcher.call(), the raw JSON.parse'd payload reaches the tool function directly.

Fix

const schema: ZodType | undefined =
  "inputSchema" in t ? (t.inputSchema as ZodType)
  : "parameters" in t ? ((t as Record<string, unknown>).parameters as ZodType)
  : undefined;

fns[sanitizeToolName(name)] = schema
  ? async (args: unknown) => execute(schema.parse(args))
  : execute;

🤖 Generated with Claude Code

…ution

createCodeTool() extracted execute functions from tools but discarded
their Zod schemas. This meant sandboxed code could call tool functions
with arbitrary JSON payloads that bypass the schema constraints defined
by tool authors, since ToolDispatcher.call() passes JSON.parse'd args
directly to fn() without validation.

Now each execute function is wrapped with its corresponding Zod schema
(inputSchema or parameters) so arguments are validated before reaching
the tool function. Invalid payloads throw a ZodError caught by the
existing error handler in ToolDispatcher.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@changeset-bot
Copy link

changeset-bot bot commented Feb 21, 2026

⚠️ No Changeset found

Latest commit: b35cda0

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

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.

1 participant