Skip to content

fix: validate tool_calls responses at provider boundary #22

@stackbilt-admin

Description

@stackbilt-admin

Problem

All five providers (OpenAI, Anthropic, Cerebras, Cloudflare, Groq) blindly map tool_calls from API responses into ToolCall[] with zero runtime validation:

toolCalls = choice.message.tool_calls.map(tc => ({
  id: tc.id,
  type: 'function' as const,
  function: { name: tc.function.name, arguments: tc.function.arguments }
}));

TypeScript interfaces provide compile-time shape checks, but at runtime nothing validates:

  • tc.id exists and is a string
  • tc.function.name is a non-empty string
  • tc.function.arguments is valid/parseable JSON (providers sometimes return malformed JSON)
  • The tool name matches one of the tools sent in the request

This is a system boundary (external API responses) where validation is warranted per OWASP input validation guidance.

Impact

A malformed tool_calls entry (missing id, garbage arguments, hallucinated tool name) propagates to the caller unchecked. Downstream consumers (e.g. AEGIS dispatch) would fail with opaque errors or silently pass bad data.

Affected files

  • src/providers/openai.ts (line ~358)
  • src/providers/anthropic.ts (line ~426)
  • src/providers/cerebras.ts (line ~382)
  • src/providers/cloudflare.ts (line ~493)
  • src/providers/groq.ts (line ~378)

Suggested approach

  1. Add a shared validateToolCalls(raw, requestedTools?) helper in src/utils/ or src/providers/base.ts
  2. Validate shape: id is string, function.name is non-empty string, function.arguments is string
  3. Optionally validate arguments is parseable JSON (warn or strip if not)
  4. Optionally validate tool name is in the set of requested tools (warn if not)
  5. Call from each provider's formatResponse before returning

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions