fix: publish Castiron checks for external-fork pull requests - #2464
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Castiron custom code✅ No new custom-code files detected. 32 mixed files remain; 2 existing customizations changed. Compared
30 existing customizations unchanged
A changed generated baseline means this report cannot reliably identify which handwritten lines changed. Inspect the custom-code diffDownload the exact patch produced by this run (requires repository access): gh run download 32879001656 --repo openai/openai-node \
--name castiron-custom-code-32879001656-1 --dir /tmp/castiron-custom-code-32879001656-1
git apply --stat /tmp/castiron-custom-code-32879001656-1/custom-code.patch
cat /tmp/castiron-custom-code-32879001656-1/custom-code.patchOr reproduce it from an SDK checkout containing the vendored reporter: git fetch --no-tags origin c100c832962ec42e7777ba506bba9b34e3520d52 ee9ee16e1715f41436bfef6f5954d353f9e9a064
python3 scripts/castiron/custom_code_report.py report \
--base c100c832962ec42e7777ba506bba9b34e3520d52 \
--head ee9ee16e1715f41436bfef6f5954d353f9e9a064 --fetch --require-head-hash --public \
--out /tmp/castiron-custom-code-ee9ee16e1715
cat /tmp/castiron-custom-code-ee9ee16e1715/custom-code.patchThis is the current full custom patch for mixed files, not an attribution of only the handwritten lines changed by this PR. |
jbeckwith-oai
left a comment
There was a problem hiding this comment.
Reviewed the fork workflow-run association and privileged Castiron reporting paths, including independent upstream PR/head/source-repository/base validation, stale-run handling, artifact isolation, least-privilege status/comment publication, and the expanded security regression coverage. LGTM.
apcha-oai
left a comment
There was a problem hiding this comment.
[sdk codex review] Approving ee9ee16e1715f41436bfef6f5954d353f9e9a064 after two independent full reviews of all six changed files and their reporting/publication contracts. No substantiated blocking issue found.
Fork-side associations remain discovery hints: the resolver and both privileged publishers re-fetch upstream PRs and validate source repository, exact head, open state, intended base and a single current association. Trusted computation/artifact boundaries, least-privilege permissions, stale-run handling and merge-group checks remain intact. The new regressions exercise the actual embedded publisher JavaScript; no duplicate review comments are needed.
Primary Castiron CI checked out this exact head, verified the reporter checksum, and ran 60 focused tests successfully with one skip. Node CI passed the Node 22/24/26 test matrix at the head, plus lint/type checks. OkTest passed 237 tests across 42 suites on merge 8c497a860f716e4e7111d64fcc711ca1b66b0a2f (head + base c100c832). Subsequent observed main changes affect only pnpm-lock.yaml, with no overlap with these workflow/Python paths; these results are not execution against that newer main.
Head, PR base, live base, author, open/non-draft status and mergeability rechecked before submission. Validation used source review, existing hosted logs and read-only GitHub API observations—not new scans, candidate execution or a deployed privileged fork-publisher test.
Automated Release PR --- ## [7.6.0](openai/openai-node@v7.5.0...v7.6.0) (2026-08-26) ### Features * **api:** Add obfuscation field to ChatCompletionChunk ([openai#2423](openai#2423)) ([39afa3a](openai@39afa3a)) * **api:** Add project residency and usage quantity_unit fields ([openai#2461](openai#2461)) ([26d8158](openai@26d8158)) * **api:** support backend-mediated Realtime WebRTC calls ([openai#2469](openai#2469)) ([0d12ca8](openai@0d12ca8)) * **auth:** add pinned X.509 workload token exchange ([openai#2470](openai#2470)) ([9dd8648](openai@9dd8648)) * **auth:** attest cross-module X.509 transport capabilities ([openai#2471](openai#2471)) ([c6769fa](openai@c6769fa)) * **auth:** harden X.509 token lifecycle and tenant isolation ([openai#2473](openai#2473)) ([6992683](openai@6992683)) * **auth:** integrate attested X.509 workload identity into clients ([openai#2472](openai#2472)) ([ee5229b](openai@ee5229b)) * support named data-residency endpoints ([openai#2393](openai#2393)) ([62d98dd](openai@62d98dd)) ### Bug Fixes * [responses] Avoid quadratic comparisons when accumulating long text ([openai#2434](openai#2434)) ([95628ce](openai@95628ce)) * **assistants:** reject run-step identity hijacking before tool callbacks ([openai#2476](openai#2476)) ([63b1c75](openai@63b1c75)) * **audio:** preserve recording outcomes during cancellation and cleanup ([openai#2482](openai#2482)) ([dafcac4](openai@dafcac4)) * **auth:** honor an explicit zero GCP metadata timeout ([openai#2481](openai#2481)) ([7a9dec8](openai@7a9dec8)) * **auth:** sanitize malformed Azure IMDS token responses ([openai#2427](openai#2427)) ([bbfb792](openai@bbfb792)) * **auth:** sanitize malformed workload OAuth token responses ([openai#2468](openai#2468)) ([cd5b2d8](openai@cd5b2d8)) * avoid double-counting logprobs in streamed chat completions ([openai#2444](openai#2444)) ([ddf9922](openai@ddf9922)) * **bedrock:** honor cancellation during bearer credential resolution ([openai#2478](openai#2478)) ([2dac2f4](openai@2dac2f4)) * drain tee stream queues in linear time ([openai#2379](openai#2379)) ([1f3ce07](openai@1f3ce07)) * **polling:** honor cancellation during polling delays ([openai#2477](openai#2477)) ([520d604](openai@520d604)) * preserve large streaming responses ([openai#2433](openai#2433)) ([4e588c2](openai@4e588c2)) * preserve multipart upload array order ([openai#2380](openai#2380)) ([f1a2b61](openai@f1a2b61)) * publish Castiron checks for behind-main pull requests ([openai#2486](openai#2486)) ([662bb37](openai@662bb37)) * publish Castiron checks for external-fork pull requests ([openai#2464](openai#2464)) ([a90581e](openai@a90581e)) * **security:** abort streaming examples when clients disconnect ([openai#2426](openai#2426)) ([b32a25b](openai@b32a25b)) * **security:** authenticate Cloudflare tests and restrict streaming proxies ([openai#2413](openai#2413)) ([9286fdb](openai@9286fdb)) * **security:** authenticate Vercel ecosystem APIs and clean up uploaded files ([openai#2412](openai#2412)) ([d58608a](openai@d58608a)) * **security:** bound SDK event streams and validate streamed item identities ([openai#2415](openai#2415)) ([7df29a9](openai@7df29a9)) * **security:** bound SSE frames and NDJSON lines before buffering ([openai#2411](openai#2411)) ([0e250a4](openai@0e250a4)) * **security:** close rejected Azure managed-identity response streams ([openai#2416](openai#2416)) ([387bbc8](openai@387bbc8)) * **security:** harden Bedrock regions, query merges, and upload errors ([openai#2410](openai#2410)) ([ce45d0d](openai@ce45d0d)) * **security:** harden Realtime WebSocket origins, worker guards, and Azure credentials ([openai#2414](openai#2414)) ([5533f73](openai@5533f73)) * **security:** preserve chat structured response-format integrity ([openai#2402](openai#2402)) ([e69df93](openai@e69df93)) * **security:** prevent AssistantStream deltas leaking sensitive data ([openai#2392](openai#2392)) ([17cf54c](openai@17cf54c)) * **security:** prevent streaming upload filename path disclosure ([openai#2386](openai#2386)) ([c88a024](openai@c88a024)) * **security:** prevent structured-output format downgrade ([openai#2394](openai#2394)) ([dd945e6](openai@dd945e6)) * **security:** redact built-in structured JSON parse errors ([openai#2418](openai#2418)) ([a0d68cc](openai@a0d68cc)) * **security:** redact chat completion finalization snapshots ([openai#2400](openai#2400)) ([fb5d8e7](openai@fb5d8e7)) * **security:** redact GCP metadata authentication error bodies ([openai#2399](openai#2399)) ([322840c](openai@322840c)) * **security:** redact invalid Bedrock bearer credentials ([openai#2419](openai#2419)) ([39c06d1](openai@39c06d1)) * **security:** redact invalid workload identity access tokens ([openai#2425](openai#2425)) ([0d28da3](openai@0d28da3)) * **security:** redact malformed NDJSON stream diagnostics ([openai#2420](openai#2420)) ([dcc705c](openai@dcc705c)) * **security:** redact malformed Realtime WebSocket error causes ([openai#2408](openai#2408)) ([e7a1a44](openai@e7a1a44)) * **security:** redact malformed SSE diagnostic payloads ([openai#2403](openai#2403)) ([272a2cc](openai@272a2cc)) * **security:** redact sensitive assistant delta diagnostics ([openai#2406](openai#2406)) ([b130b83](openai@b130b83)) * **security:** redact unsupported Responses stream event payloads ([openai#2395](openai#2395)) ([32b2953](openai@32b2953)) * **security:** reject malformed Realtime WebSocket event frames ([openai#2391](openai#2391)) ([e6e11b0](openai@e6e11b0)) * **security:** require an exact SSE completion sentinel ([openai#2422](openai#2422)) ([a905bfb](openai@a905bfb)) * **security:** require OIDC for npm publishing ([openai#2404](openai#2404)) ([342764b](openai@342764b)) * **security:** respect configured logger for Assistants stream errors ([openai#2390](openai#2390)) ([8ba3009](openai@8ba3009)) * **security:** restrict live CI credentials to protected main ([openai#2405](openai#2405)) ([3554cdc](openai@3554cdc)) * **security:** scope Cloudflare ecosystem API key files ([openai#2398](openai#2398)) ([4f4b45d](openai@4f4b45d)) * **security:** secure Next.js Edge streaming example requests ([openai#2424](openai#2424)) ([861caed](openai@861caed)) * **security:** stop delayed and additional tool callbacks after cancellation ([openai#2430](openai#2430)) ([c168599](openai@c168599)) * **security:** stop retaining sensitive assistant stream events ([openai#2407](openai#2407)) ([dfec129](openai@dfec129)) * settle concurrent stream event waiters in linear time ([openai#2387](openai#2387)) ([a88c2ca](openai@a88c2ca)) * settle WebSocket event waiters in linear time ([openai#2389](openai#2389)) ([489dc72](openai@489dc72)) * **standard-schema:** preserve validator bindings across helpers ([openai#2483](openai#2483)) ([e4afdb7](openai@e4afdb7)) * **streaming:** reject named SSE provider error events ([openai#2409](openai#2409)) ([b7a0bd6](openai@b7a0bd6)) * **tests:** make credential-lifecycle held-inode scenarios portable to macOS ([openai#2480](openai#2480)) ([60f5267](openai@60f5267)) * **uploads:** preserve Blob files and multipart media types ([openai#2467](openai#2467)) ([d497fb3](openai@d497fb3)) * **webhooks:** bound signature verification work ([openai#2475](openai#2475)) ([05cf7ab](openai@05cf7ab)) * **ws:** block custom credential headers on redirects ([openai#2429](openai#2429)) ([d2ab6e7](openai@d2ab6e7)) * **zod:** support only provably JSON-native structured outputs ([openai#2396](openai#2396)) ([c3d68e4](openai@c3d68e4)) ### Chores * **api:** clarify image transparency and audio delta docs ([openai#2439](openai#2439)) ([f14e885](openai@f14e885)) * **api:** document supported image generation models ([openai#2432](openai#2432)) ([0e00909](openai@0e00909)) * **api:** update SDK generation metadata ([openai#2448](openai#2448)) ([d1410d1](openai@d1410d1)) * **deps-dev:** bump @cloudflare/workers-types from 5.20260809.1 to 5.20260816.1 in /ecosystem-tests/cloudflare-worker ([openai#2452](openai#2452)) ([cf7e588](openai@cf7e588)) * **deps-dev:** bump @smithy/hash-node from 4.4.16 to 4.5.2 ([openai#2455](openai#2455)) ([342b0a3](openai@342b0a3)) * **deps-dev:** bump @smithy/signature-v4 from 5.6.12 to 5.7.2 ([openai#2459](openai#2459)) ([bf4386c](openai@bf4386c)) * **deps-dev:** bump publint from 0.3.22 to 0.3.23 ([openai#2457](openai#2457)) ([c100c83](openai@c100c83)) * **deps-dev:** bump puppeteer from 25.5.0 to 25.7.0 in /ecosystem-tests/browser-direct-import ([openai#2451](openai#2451)) ([c6c406b](openai@c6c406b)) * **deps-dev:** bump puppeteer from 25.5.0 to 25.7.0 in /ecosystem-tests/ts-browser-webpack ([openai#2456](openai#2456)) ([e1faab1](openai@e1faab1)) * **deps-dev:** bump ws from 8.21.1 to 8.21.3 ([openai#2454](openai#2454)) ([1f84889](openai@1f84889)) * **deps:** bump next from 15.5.21 to 15.5.23 in /ecosystem-tests/vercel-edge ([openai#2458](openai#2458)) ([cc532b3](openai@cc532b3)) * **deps:** bump next from 16.3.0 to 16.3.1 ([openai#2460](openai#2460)) ([a2d88c1](openai@a2d88c1)) * set a 3,000-line custom-code budget ([openai#2446](openai#2446)) ([2035847](openai@2035847)) ### Documentation * encode recurring SDK review feedback in agent guidance ([openai#2378](openai#2378)) ([e552523](openai@e552523)) * **security:** add secure contributor and agent guidance ([openai#2382](openai#2382)) ([459d009](openai@459d009)) ### Refactors * move embedding encoding into an SDK-owned helper ([openai#2436](openai#2436)) ([db9e930](openai@db9e930)) * move file processing wait into an SDK-owned helper ([openai#2438](openai#2438)) ([3d39e64](openai@3d39e64)) * move vector store batch uploads into an SDK-owned helper ([openai#2441](openai#2441)) ([0257e51](openai@0257e51)) * move vector store polling into an SDK-owned helper ([openai#2437](openai#2437)) ([4317319](openai@4317319)) * move webhook signature checks into an SDK-owned helper ([openai#2442](openai#2442)) ([283e12b](openai@283e12b)) * share SDK-owned assistant run polling ([openai#2440](openai#2440)) ([4de295b](openai@4de295b)) --- 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>
Summary
GitHub omits
workflow_run.pull_requestsfor external-fork runs, and querying the upstream repository's commit-association endpoint returns no pull requests for those fork commits. That leaves the requiredCastiron / budget-only changeandCastiron / custom-code budgetcontexts permanently expected even when the candidate workflow succeeds.custom_code_report.pyand reuse it from trusted report generation, comment publication, and budget evaluation.head_repository, including legitimately renamed forks, then independently re-fetch every candidate PR fromopenai/openai-node.Security model
Fork-side associations and PR numbers are discovery hints, never authorization. The trusted paths:
head_repositorymetadata; reject traversal-like components and spoofed identities.mainbase ref, and exactly one valid current association.mainbase SHA wherever budget evaluation or status publication needs freshness; preserve existing stale-run behavior and merge-group validation.The existing trusted
workflow_run/main-checkout boundary, bare Git object store, candidate-artifact isolation, least-privilege job permissions, merge-queue protections, and exact required status names remain unchanged. No candidate workflow definition, mutable ref, contributor artifact, or fork-supplied PR number is trusted.Affected contributor PRs
32877584723haspull_requests: []; the updated resolver correctly finds its upstream PR throughcmun2/openai-node.Verification
env PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s scripts/castiron -p 'test_custom_code*.py'— 60 tests pass, with one pre-existing skip.go run github.com/rhysd/actionlint/cmd/actionlint@latest .github/workflows/castiron-custom-code.yml .github/workflows/castiron-custom-code-comment.yml— both workflows pass actionlint v1.7.12.ruff format --check scripts/castiron/custom_code_report.py scripts/castiron/custom_code_budget.py scripts/castiron/test_custom_code_report.py scripts/castiron/test_custom_code_budget.py.git diff --checkpasses.