Skip to content

fix(assistants): reject root IDs in run-step deltas - #2698

Merged
HAYDEN-OAI merged 1 commit into
mainfrom
fix/assistant-run-step-delta-id-focused
Sep 8, 2026
Merged

HAYDEN-OAI merged 1 commit into
mainfrom
fix/assistant-run-step-delta-id-focused

Conversation

@HAYDEN-OAI

Copy link
Copy Markdown
Contributor

Supersedes #2685.

Run-step deltas must not carry a root id. Reject that field before raw-event dispatch and recheck the captured delta immediately before accumulation, so an ordinary raw listener cannot introduce it between validation and merging. A listener-added root ID rejects the event instead of being silently stripped.

This keeps run-step identity out of delta accumulation while preserving valid callback objects, nested tool-call IDs, extension properties, and existing alias handling. The production change is 14 additions and 3 deletions in AssistantStream.ts.

Scope

The security guarantee covers decoded SSE/NDJSON protocol data. The pre-merge check also covers ordinary listener additions and replacements. It follows the repository's documented distinction between protocol data and executable application authority; arbitrary hostile getters, Proxies, and callback code running with application authority are outside this change's security guarantee.

Validation

  • Added 14 focused cases covering both byte-decoding entrypoints: rejection before raw dispatch, listener-added/replaced root IDs, and preservation of valid callback identity, nested IDs, and extension fields.
  • All 278 tests across the seven AssistantStream suites pass on Node 24.20.0 using ./scripts/test tests/lib/AssistantStream.test.ts tests/lib/assistant-stream.
  • All 51 run-step identity tests pass on exact minimum Node 22.0.0.
  • Canonical pnpm lint, full pnpm exec tsc, and pnpm build pass with the pinned dependencies.
  • Built AssistantStream CJS/ESM imports pass on Node 22.0.0 and 24.20.0.
  • One independent static review found no actionable issues within the stated scope.

Validation uses focused rejection tests; the original heap-exhaustion experiment was not rerun.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-08T17:33:52.431217Z 99110fc PR opened
🔒 Security Review ✅ Completed 2026-09-08T17:35:01.685460Z 99110fc PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@openai-sdks

openai-sdks Bot commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

OkTest Summary

✅ 236/236 SDK tests passed in 9.77s for Node SDK PR #2698.

Test results — 42 files
Test Result Time
tests/chat-completions-complex-body.test.ts ✅ Passed 143ms
tests/chat-completions-create.test.ts ✅ Passed 157ms
tests/chat-completions-stream.test.ts ✅ Passed 141ms
tests/files-content-binary.test.ts ✅ Passed 233ms
tests/files-create-multipart.test.ts ✅ Passed 212ms
tests/files-list-pagination.test.ts ✅ Passed 174ms
tests/initialize-config.test.ts ✅ Passed 143ms
tests/instance-isolation.test.ts ✅ Passed 163ms
tests/models-list.test.ts ✅ Passed 246ms
tests/responses-background-lifecycle.test.ts ✅ Passed 168ms
tests/responses-body-method-errors.test.ts ✅ Passed 225ms
tests/responses-cancel-timeout.test.ts ✅ Passed 226ms
tests/responses-cancel.test.ts ✅ Passed 263ms
tests/responses-compact-retries.test.ts ✅ Passed 183ms
tests/responses-compact.test.ts ✅ Passed 246ms
tests/responses-create-advanced-stream.test.ts ✅ Passed 78ms
tests/responses-create-advanced.test.ts ✅ Passed 136ms
tests/responses-create-disconnect.test.ts ✅ Passed 985ms
tests/responses-create-errors.test.ts ✅ Passed 308ms
tests/responses-create-malformed-api-responses.test.ts ✅ Passed 251ms
tests/responses-create-retries.test.ts ✅ Passed 192ms
tests/responses-create-stream-failures.test.ts ✅ Passed 172ms
tests/responses-create-stream-timeout.test.ts ✅ Passed 2.141s
tests/responses-create-stream-wire.test.ts ✅ Passed 2.15s
tests/responses-create-stream.test.ts ✅ Passed 92ms
tests/responses-create-terminal-states.test.ts ✅ Passed 189ms
tests/responses-create-timeout.test.ts ✅ Passed 213ms
tests/responses-create.test.ts ✅ Passed 268ms
tests/responses-delete.test.ts ✅ Passed 233ms
tests/responses-input-items-errors.test.ts ✅ Passed 171ms
tests/responses-input-items-list.test.ts ✅ Passed 145ms
tests/responses-input-items-options.test.ts ✅ Passed 180ms
tests/responses-input-tokens-count-timeout.test.ts ✅ Passed 172ms
tests/responses-input-tokens-count.test.ts ✅ Passed 172ms
tests/responses-malformed-inputs.test.ts ✅ Passed 1.733s
tests/responses-not-found-errors.test.ts ✅ Passed 436ms
tests/responses-parse.test.ts ✅ Passed 203ms
tests/responses-retrieve-retries.test.ts ✅ Passed 185ms
tests/responses-retrieve.test.ts ✅ Passed 151ms
tests/responses-stored-method-errors.test.ts ✅ Passed 489ms
tests/retry-behavior.test.ts ✅ Passed 3.106s
tests/sdk-error-shape.test.ts ✅ Passed 479ms

View OkTest run #34257705656

SDK merge (7964f0f32649) · head (99110fc2713a) · base (bb0f51bed84b) · OkTest (08ec4299e769)

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Castiron custom code

✅ No new custom-code files detected.

32 mixed files remain; 0 existing customizations changed.

Compared 80ce89f355dd → 99110fc2713a. Generated baselines verified.

32 existing customizations unchanged
  • api.md
  • scripts/castiron/README.md
  • scripts/castiron/custom_code_report.py
  • scripts/castiron/test_custom_code_report.py
  • src/client.ts
  • src/resources/audio/transcriptions.ts
  • src/resources/audio/translations.ts
  • src/resources/beta/assistants.ts
  • src/resources/beta/beta.ts
  • src/resources/beta/index.ts
  • src/resources/beta/responses/internal-base.ts
  • src/resources/beta/responses/responses.ts
  • src/resources/beta/threads/index.ts
  • src/resources/beta/threads/runs/index.ts
  • src/resources/beta/threads/runs/runs.ts
  • src/resources/beta/threads/threads.ts
  • src/resources/chat/completions/completions.ts
  • src/resources/chat/completions/index.ts
  • src/resources/conversations/index.ts
  • src/resources/embeddings.ts
  • src/resources/files.ts
  • src/resources/fine-tuning/checkpoints/permissions.ts
  • src/resources/images.ts
  • src/resources/responses/internal-base.ts
  • src/resources/responses/responses.ts
  • src/resources/skills/skills.ts
  • src/resources/skills/versions/versions.ts
  • src/resources/vector-stores/file-batches.ts
  • src/resources/vector-stores/files.ts
  • src/resources/webhooks/index.ts
  • src/resources/webhooks/webhooks.ts
  • tests/lib/data-residency.test.ts

A changed generated baseline means this report cannot reliably identify which handwritten lines changed.

Inspect the custom-code diff

Download the exact patch produced by this run (requires repository access):

gh run download 34257752171 --repo openai/openai-node \
  --name castiron-custom-code-34257752171-1 --dir /tmp/castiron-custom-code-34257752171-1
git apply --stat /tmp/castiron-custom-code-34257752171-1/custom-code.patch
cat /tmp/castiron-custom-code-34257752171-1/custom-code.patch

Or reproduce it from an SDK checkout containing the vendored reporter:

git fetch --no-tags origin bb0f51bed84bf60b0639af7a894fcf538264e435 99110fc2713aa382f4162c79d9e8d42f96d51d4c
python3 scripts/castiron/custom_code_report.py report \
  --base bb0f51bed84bf60b0639af7a894fcf538264e435 \
  --head 99110fc2713aa382f4162c79d9e8d42f96d51d4c --fetch --require-head-hash --public \
  --out /tmp/castiron-custom-code-99110fc2713a
cat /tmp/castiron-custom-code-99110fc2713a/custom-code.patch

This is the current full custom patch for mixed files, not an attribution of only the handwritten lines changed by this PR.

Full report and patch

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

Reviewed the exact 2-file patch against the requested outcome: reject root run-step delta IDs before raw SSE/serialized dispatch and again after ordinary raw-listener mutation immediately before accumulation, while preserving callback object identity, nested tool-call IDs, extension fields, and existing alias behavior. The new checks are placed at both mutation boundaries and do not broaden into Proxy/getter hardening outside the documented application-authority scope. The full seven-suite AssistantStream target passes locally: 278 tests. Git diff check passes, no public API or generated/runtime surface beyond the 14-line accumulator validation changes, no unresolved threads, and every exact-head lint/build/Node 22/24/26/ecosystem/CodeQL/Castiron check is green. No blocking findings.

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

Reviewed 99110fc against merge-base 80ce89f. No actionable correctness or structural findings.

Both checks are justified: decoded root IDs must fail before raw dispatch, while ordinary listeners can modify or replace the delta before accumulation. Capturing and checking that delta immediately before merging preserves valid callback identity, nested tool-call IDs, extension fields, and the existing canonical-ID/alias handling. I read the repository security model and evaluated its protocol-data/application-authority distinction. A shared recursive prohibition would incorrectly reject nested IDs; a single check would lose one timing guarantee. No additional ownership framework is warranted. File sizes are 1,025→1,036 lines for AssistantStream and 647→745 for the identity tests; neither newly crosses 1,000 lines.

Fresh validation: 278 tests across seven AssistantStream suites passed on Node 24.20.0; all 51 identity tests passed on exact Node 22.0.0. Independent SSE/NDJSON probes reproduced root-ID accumulation using the merge-base AssistantStream and confirmed protocol/listener rejection, error/end ordering, and valid identity/nested-ID/extension preservation at this head. Build passed on Node 24.20.0; AssistantStream CJS/ESM imports passed on both runtimes. Diff whitespace checks passed.

Validation limits: internal js installation and pinned pnpm installation were blocked by tooling/registry access, so execution used cached dependencies (Vitest 4.1.11, TypeScript 6.0.3). Canonical lint passed with cached Oxlint 1.79.0 rather than pinned 1.80.0. Full type checking could not pass because example dependencies dotenv, @azure/identity, and express were unavailable. These are validation limits, not patch findings. No heap-exhaustion experiment was rerun.

@HAYDEN-OAI
HAYDEN-OAI added this pull request to the merge queue Sep 8, 2026
@HAYDEN-OAI HAYDEN-OAI added the codex-security Result of a Codex Security scan label Sep 8, 2026
Merged via the queue into main with commit 63dfa4c Sep 8, 2026
38 checks passed
@HAYDEN-OAI
HAYDEN-OAI deleted the fix/assistant-run-step-delta-id-focused branch September 8, 2026 18:25
@openai-sdks openai-sdks Bot mentioned this pull request Sep 8, 2026
gh-actions-shared Bot pushed a commit to xf-qubit/openai-node that referenced this pull request Sep 9, 2026
Automated Release PR
---


##
[7.12.0](openai/openai-node@v7.11.0...v7.12.0)
(2026-09-08)


### Features

* **api:** add GPT Image 2.5 models and image options
([openai#2705](openai#2705))
([6500a16](openai@6500a16))


### Bug Fixes

* **assistants:** reject root IDs in run-step deltas
([openai#2698](openai#2698))
([63dfa4c](openai@63dfa4c))
* **files:** use a monotonic clock for processing timeout
([openai#2657](openai#2657))
([bb0f51b](openai@bb0f51b))
* preserve suppressed workload authorization
([openai#2699](openai#2699))
([57bbfd3](openai@57bbfd3))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex-security Result of a Codex Security scan

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants