Skip to content

fix(security): preserve chat structured response-format integrity - #2402

Merged
HAYDEN-OAI merged 1 commit into
mainfrom
agent/chat-schema-serialization-security-svmfcodj
Aug 18, 2026
Merged

HAYDEN-OAI merged 1 commit into
mainfrom
agent/chat-schema-serialization-security-svmfcodj

Conversation

@HAYDEN-OAI

Copy link
Copy Markdown
Contributor

Summary

  • Protect Chat Completions structured-output schemas from caller-supplied metadata serializers that silently replace the model-visible schema, trusted name, or strict: true.
  • Clone the nested json_schema configuration before removing its own toJSON hook, preserving frozen inputs, ordinary metadata, enumerable symbols, and validated local parsing.
  • Apply the same canonical json_schema discriminator and root serializer protections already used by Responses text-format helpers.
  • Keep all changes in the shared handwritten parser factory; no Zod or Standard Schema helper source, existing helper tests, generated files, or active user-owned PR paths are changed.

Security impact

Both public zodResponseFormat() and standardResponseFormat() spread caller metadata into response_format.json_schema. An enumerable function or getter named toJSON is retained there and invoked by real request serialization. Consequently, client.chat.completions.parse() sends attacker-selected { name, strict: false, schema } even though the SDK's in-memory format still advertises the trusted strict schema and its branded parser validates returned output. The issue affects Zod v3, Zod v4, Zod v4 Mini, and Standard Schema.

Validation

  • Independently reproduced all eight real public client.chat.completions.parse() combinations: four schema families × own callable/accessor serializer.
  • Regression-first: 16 security/direct-factory failures on unchanged main; 12 existing-behavior controls already passed.
  • 28 dedicated regressions: actual serialized Chat Completions requests, frozen caller/nested objects, ordinary metadata, symbols, getters, inherited/non-enumerable hooks, canonical type, parser descriptors, validation, and public mutability.
  • Existing structured Responses safeguards: 76 tests passed.
  • Full handwritten suite: 110 files, 3,353 tests passed.
  • Full generated API suite: 82 files, 559 tests passed (one existing skipped).
  • Formatting/lint: zero warnings/errors.
  • Repository TypeScript compilation and clean CommonJS/ESM build.
  • Published declaration checks on TypeScript 4.9 and current TypeScript.
  • Packed npm artifact: CommonJS, ESM, and 267/304 source checks across 1,216 source maps.

Exactly two handwritten files are changed.

@openai-sdks

openai-sdks Bot commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

OkTest Summary

✅ 237/237 SDK tests passed in 10.999s for Node SDK PR #2402.

Test results — 42 files
Test Result Time
tests/chat-completions-complex-body.test.ts ✅ Passed 206ms
tests/chat-completions-create.test.ts ✅ Passed 300ms
tests/chat-completions-stream.test.ts ✅ Passed 214ms
tests/files-content-binary.test.ts ✅ Passed 146ms
tests/files-create-multipart.test.ts ✅ Passed 169ms
tests/files-list-pagination.test.ts ✅ Passed 166ms
tests/initialize-config.test.ts ✅ Passed 154ms
tests/instance-isolation.test.ts ✅ Passed 102ms
tests/models-list.test.ts ✅ Passed 162ms
tests/responses-background-lifecycle.test.ts ✅ Passed 276ms
tests/responses-body-method-errors.test.ts ✅ Passed 316ms
tests/responses-cancel-timeout.test.ts ✅ Passed 207ms
tests/responses-cancel.test.ts ✅ Passed 226ms
tests/responses-compact-retries.test.ts ✅ Passed 238ms
tests/responses-compact.test.ts ✅ Passed 259ms
tests/responses-create-advanced-stream.test.ts ✅ Passed 141ms
tests/responses-create-advanced.test.ts ✅ Passed 169ms
tests/responses-create-disconnect.test.ts ✅ Passed 1.156s
tests/responses-create-errors.test.ts ✅ Passed 228ms
tests/responses-create-malformed-api-responses.test.ts ✅ Passed 179ms
tests/responses-create-retries.test.ts ✅ Passed 257ms
tests/responses-create-stream-failures.test.ts ✅ Passed 263ms
tests/responses-create-stream-timeout.test.ts ✅ Passed 2.206s
tests/responses-create-stream-wire.test.ts ✅ Passed 2.706s
tests/responses-create-stream.test.ts ✅ Passed 107ms
tests/responses-create-terminal-states.test.ts ✅ Passed 238ms
tests/responses-create-timeout.test.ts ✅ Passed 228ms
tests/responses-create.test.ts ✅ Passed 242ms
tests/responses-delete.test.ts ✅ Passed 210ms
tests/responses-input-items-errors.test.ts ✅ Passed 181ms
tests/responses-input-items-list.test.ts ✅ Passed 183ms
tests/responses-input-items-options.test.ts ✅ Passed 106ms
tests/responses-input-tokens-count-timeout.test.ts ✅ Passed 246ms
tests/responses-input-tokens-count.test.ts ✅ Passed 255ms
tests/responses-malformed-inputs.test.ts ✅ Passed 2.409s
tests/responses-not-found-errors.test.ts ✅ Passed 264ms
tests/responses-parse.test.ts ✅ Passed 223ms
tests/responses-retrieve-retries.test.ts ✅ Passed 270ms
tests/responses-retrieve.test.ts ✅ Passed 271ms
tests/responses-stored-method-errors.test.ts ✅ Passed 705ms
tests/retry-behavior.test.ts ✅ Passed 3.118s
tests/sdk-error-shape.test.ts ✅ Passed 338ms

View OkTest run #32182536954

SDK merge (979d86f22652) · head (3ed4a196c3e6) · base (4ff0bf77fa3e) · OkTest (7e7850017529)

@jbeckwith-oai jbeckwith-oai 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.

Independent two-pass security review confirms chat structured response-format integrity across Zod v3, Zod v4, Zod v4 Mini, and Standard Schema. The shared factory canonicalizes the discriminator, isolates both format levels, removes callable and accessor serialization hooks, preserves branded parsers and immutable inputs, and retains streaming/nonstreaming compatibility. Focused adversarial tests and CI are green. No findings.

@HAYDEN-OAI
HAYDEN-OAI added this pull request to the merge queue Aug 18, 2026
Merged via the queue into main with commit e69df93 Aug 18, 2026
27 checks passed
@HAYDEN-OAI
HAYDEN-OAI deleted the agent/chat-schema-serialization-security-svmfcodj branch August 18, 2026 20:45
@openai-sdks openai-sdks Bot mentioned this pull request Aug 18, 2026

This branch was successfully deployed

1 active deployment
ci — 3ed4a196 Deployed Aug 18, 2026 by HAYDEN-OAI via ecosystem tests #8490
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants