fix(openrouter): bound video model catalog JSON response reads#96500
fix(openrouter): bound video model catalog JSON response reads#96500hugenshen wants to merge 1 commit into
Conversation
The video model catalog endpoint used an unbounded await response.json() to parse the OpenRouter video models list. Route through readProviderJsonResponse (16 MiB cap) to match the bound already in place for the chat/text model catalog paths. AI-assisted. Co-authored-by: Cursor <[email protected]>
|
Codex review: needs maintainer review before merge. Reviewed June 24, 2026, 12:53 PM ET / 16:53 UTC. Summary PR surface: Source +4. Total +4 across 1 file. Reproducibility: yes. Current main has a source-level reproduction path because Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land one bounded-reader implementation for this path, keeping the shared provider JSON cap; this minimal PR is valid, while #96505 is the alternative if maintainers require a direct catalog-path regression test before merge. Do we have a high-confidence way to reproduce the issue? Yes. Current main has a source-level reproduction path because Is this the best way to solve the issue? Yes. Reusing AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 4ae0a5d958a0. Label changesLabel justifications:
Evidence reviewedPR surface: Source +4. Total +4 across 1 file. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
Thanks for the fix. This overlaps the same OpenRouter video catalog parser change as #96505, and we are going to use #96505 as the canonical landing path. The production change is effectively the same, but #96505 also updates the existing OpenRouter provider test fixture to use real Closing this as superseded by #96505. |
What Problem This Solves
The OpenRouter video model catalog endpoint (
fetchOpenRouterVideoModelsinextensions/openrouter/video-model-catalog.ts) reads its success response withan unbounded
await response.json(). The chat/text model catalog paths in thesame codebase were already bounded via
readProviderJsonResponsein the priorresponse-limit campaign (
#95418,#95420), but the video-specific catalogendpoint was overlooked — leaving an asymmetric gap where one catalog path is
bounded and another is not.
A misbehaving, compromised, or hostile OpenRouter endpoint (including a
self-hosted
baseUrloverride) can stream an arbitrarily large model list intomemory on the video catalog discovery path, causing memory pressure or a hang.
Changes
extensions/openrouter/video-model-catalog.ts: addsreadProviderJsonResponseto the existing
openclaw/plugin-sdk/provider-httpimport and replaces(await response.json()) as OpenRouterVideoModelsResponsewithreadProviderJsonResponse<OpenRouterVideoModelsResponse>(response, "openrouter.video-model-catalog")(16 MiB cap). No other changes — one call site, one import addition.
Real behavior proof
Content-Lengthand an oversized/never-ending body must not be buffered whole;the read must stop at the cap, cancel the stream, and throw a bounded error —
while normal catalog responses parse unchanged.
node:httpserver (createServer) boundto
127.0.0.1, streaming a JSON body in 64 KiB chunks with noContent-Length header, driving the real exported
readResponseWithLimithelper (the same helper
readProviderJsonResponsewraps internally) onNode v22.22.0.
GET /hugestreams ~24 MiB with noContent-Length;GET /smallreturns one valid model catalog entry.readResponseWithLimit(response, 1 MiB)against/hugeand assertit rejects + stream is cancelled.
await response.json()path and measuretotal bytes pushed.
/smalland assert the catalog is parsed intact.openrouter.video-model-catalog: JSON response exceeds 1048576 bytes;server socket closed early; only 1,064,178 bytes reached the wire.
response.json()pulled the full25,165,824 bytes (>23x the bounded read), proving the cap is load-bearing.
ALL PROOF ASSERTIONS PASSED. No dedicated test fileexists for this catalog path; overflow/cancel coverage is provided by the
packages/media-corereadResponseWithLimitunit tests already in CI.instead measures bytes-on-wire and early socket close.
Evidence
No in-repo test file for this path. Bounded-reader enforcement is covered by
packages/media-core/src/read-response-with-limit.tsunit tests.Label: security
AI-assisted.