fix(video-generation): bound dashscope JSON response reads at 16 MiB#96782
Conversation
Replace 2 unbounded (await response.json()) calls in dashscope-compatible.ts with readProviderJsonResponse (16 MiB cap). Sites: pollDashscopeVideoTaskUntilComplete (task poll response), runDashscopeVideoGenerationTask (submit response). Reuses the existing SDK helper already used by 15+ other providers.
|
Codex review: needs maintainer review before merge. Reviewed June 26, 2026, 9:07 PM ET / 01:07 UTC. Summary PR surface: Source +13. Total +13 across 2 files. Reproducibility: yes. Current main and 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. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land one bounded-read implementation for the shared DashScope video helper, preferably this shared-helper version if maintainers accept the 16 MiB cap, then close the competing same-scope PR. Do we have a high-confidence way to reproduce the issue? Yes. Current main and 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 1bccd2930437. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +13. Total +13 across 2 files. 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
|
ClawSweeper found that the shared provider-http test mock does not export readProviderJsonResponse, causing test failures for any PR importing it. Add the mock to vi.hoisted(), the mock interface, vi.mock() exports, and installProviderHttpMockCleanup(). Default implementation delegates to response.json() to preserve existing test behavior. Co-Authored-By: Claude <[email protected]>
|
@clawsweeper re-review Added
Pre-flight: vitest 3 config shards all passed ✅ (openai video-gen 14/14, extension-providers 5/5, provider-http-errors) |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review 🦞 upgrades applied (PR body only):
No code changes. |
|
Heads up for maintainers: this PR is in re-review loop because ClawSweeper correctly identified it as a The two implementations differ only in approach:
Both are correct and both pass. From a maintainer-coordination standpoint:
I can close this one in favor of #96248 if maintainers prefer the direct approach, or keep it if the helper-based approach is preferred for campaign consistency. Either way, only one should land to avoid duplicate cap rollouts (ClawSweeper's stated P1 concern). Asking maintainers: which implementation do you want as canonical? Happy to defer. In the meantime, this PR sits in re-review loop on the coordination P1, not on any patch-quality issue. |
What Problem This Solves
src/video-generation/dashscope-compatible.tshas 2 unboundedawait response.json()calls (task poll response, submit response). A hostile DashScope endpoint or proxy can return an oversized JSON body that exhausts process memory. The download path in the same file already usesreadResponseWithLimit— this brings the submit and poll paths into the same bound-read family.Changes
No new abstraction — reuses the existing
readProviderJsonResponsehelper fromopenclaw/plugin-sdk/provider-http(16 MiB default cap, same helper used by 15+ provider plugin bounded-read PRs).src/video-generation/dashscope-compatible.ts:202,269— replace 2(await response.json()) as DashscopeVideoGenerationResponsecalls withreadProviderJsonResponse<DashscopeVideoGenerationResponse>(response, "<label>"). Labels:"${providerLabel} video-generation task poll","${providerLabel} video generation".Design Rationale
Why
readProviderJsonResponseinstead ofresponse.json()?response.json()buffers the entire HTTP body in memory before parsing — no byte-level cap.readProviderJsonResponsereads the body as a bounded stream, cancelling the underlying reader at 16 MiB (the SDK default) and throwing a canonical overflow error. This closes the OOM/DoS vector.Why the same 16 MiB cap for both submit and poll calls? Both endpoints serve JSON video-generation payloads of comparable size (typically a few KiB). Using the same threshold for both avoids distinguishing between the two at the cap level — consistency over precision.
Why no test additions? The proof exercises the exact production helper (
readProviderJsonResponse) with a real HTTP server, verifying the 16 MiB cap fires atbytesSent=20971748. The helper itself has full test coverage insrc/agents/provider-http-errors.test.ts(see thereadProviderJsonResponsedescribe block). Adding inline tests would duplicate coverage of the factory-tested helper.Real behavior proof
Behavior addressed: unbounded response.json() on 2 DashScope video-generation HTTP responses; after the fix reads are capped at 16 MiB.
Real environment tested: real node:http server on 127.0.0.1 returning a JSON body exceeding 16 MiB (20 MiB) + negative control + happy path. Node v22.22.0.
Exact steps or command run after this patch:
Evidence after fix: ```
=== dashscope video-generation JSON bounded reads (cap=16777216) ===
PASS hostile body: overflow; bytesSent=20971748; aborted=true
PASS negative control: small body parsed (task_status=SUCCEEDED)
PASS happy path: valid JSON parsed (task_id=t-123)
=== All dashscope video-generation bounded-read assertions passed ===
Observed result after fix: 3/3 assertions pass. Hostile 20 MiB body triggers overflow at 16 MiB cap (bytesSent=20971748, aborted=true). Negative control: small body parsed (task_status=SUCCEEDED). Happy path: valid JSON parsed (task_id=t-123).
What was not tested: live DashScope API call (the proof exercises the same
readProviderJsonResponsehelper against the same attack shape); cross-platform Node differences (Node 22 only, matches CI).Out of scope
response.json()sites in the codebase — covered by separate per-surface PRs (fix(openai-video-gen): bound video submit response JSON read at 16 MiB #96786 openai-video-gen, fix(chutes-oauth-plugin): bound plugin JSON response reads at 16 MiB #96779 chutes-oauth-plugin, fix(chutes-oauth): bound core helper JSON response reads at 16 MiB #96777 chutes-oauth-core, fix(comfy): bound JSON response reads via readProviderJsonResponse #96927 comfy).Risk checklist
Diff stats