fix(minimax): bound video control response reads#96889
Conversation
MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted.
|
Codex review: needs maintainer review before merge. Reviewed June 28, 2026, 10:48 AM ET / 14:48 UTC. Summary PR surface: Source +14, Tests +47. Total +61 across 3 files. Reproducibility: yes. source-reproducible with high confidence: current main directly buffers untrusted MiniMax video success/control JSON responses with Review metrics: 1 noteworthy metric.
Stored data model 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:
Next step before merge
Security Review detailsBest possible solution: Land this focused video-control hardening after maintainer review and required checks; keep image sizing on the merged image-generation path and handle OAuth/VLM through their separate PRs. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible with high confidence: current main directly buffers untrusted MiniMax video success/control JSON responses with 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 9241b9701d9c. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +14, Tests +47. Total +61 across 3 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
|
|
Updated the PR body and branch for the ClawSweeper finding: the MiniMax video |
|
Addressed the latest ClawSweeper blocker by narrowing this PR back to MiniMax video/control JSON only. The MiniMax image-provider change has been removed from this branch so image-sized response caps can be handled by the broader image-response hardening work without this PR imposing the generic 16 MiB JSON cap on inline base64 image responses. Verified current head:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted.
5642ef4 to
3679161
Compare
|
Updated this branch against latest upstream Verified current head locally:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Merge-ready for 2149eff. Local review of the updated head and ClawSweeper review clean, CI green, best narrow fix, and follows the established bounded provider JSON response-read pattern. The branch now stays correctly scoped to MiniMax video/control JSON only: task submit, status poll, and file_id metadata are bounded with readProviderJsonResponse, while the image inline-base64 response cap concern is left out of this PR. The test helper keeps the real bounded reader via importActual, and the focused regression covers oversized file_id metadata JSON failing before any binary download attempt. No maintainer edits needed. |
* fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads * fix(minimax): leave image response sizing to image hardening * fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads
* fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads * fix(minimax): leave image response sizing to image hardening * fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads
* fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads * fix(minimax): leave image response sizing to image hardening * fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads
* fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads * fix(minimax): leave image response sizing to image hardening * fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads (cherry picked from commit 25e184a)
* fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads * fix(minimax): leave image response sizing to image hardening * fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads
… OOM Replace unbounded `response.json()` in `callUserTokenService` with `readProviderJsonResponse(response, "msteams.sso-user-token")` — the same shared bounded reader already deployed across the codebase (openclaw#95218, openclaw#96322, openclaw#96495, openclaw#96889). Enforces a 16 MiB default cap and cancels the underlying stream on overflow. Closes the last unbounded JSON read on the MSTeams SSO token-exchange path. Error responses were already bounded via `extractProviderErrorDetail`. Co-Authored-By: Claude <[email protected]>
What Problem This Solves
The MiniMax video provider read several success/control-path JSON responses with unbounded
await response.json(), so a misbehaving or hostile MiniMax endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process (OOM / hang). The HTTP error path is already bounded byassertOkOrThrowHttpError; this closes the matching gap on the MiniMax video success/control side.Three video JSON reads are affected:
extensions/minimax/video-generation-provider.ts— video generation task submit responseextensions/minimax/video-generation-provider.ts— video generation status poll responseextensions/minimax/video-generation-provider.ts— video generationfile_idmetadata response before the binary downloadMiniMax TTS is already bounded and is left unchanged. MiniMax image response sizing is intentionally left out of this PR because image responses can carry large inline base64 payloads and should use an image-sized cap in the broader image-response hardening work.
Changes
readProviderJsonResponse(16 MiB cap), which cancels the underlying stream on overflow instead of buffering the whole payload.readProviderJsonResponseimplementation real viaimportActual, while continuing to mock transport/auth seams.ResponseJSON fixtures and add a focusedfile_idmetadata overflow regression proving the metadata path fails before attempting the binary download.Real behavior proof
node:httploopback server streaming a >16 MiB JSON body with no Content-Length (chunked), fetched over a real TCP socket, driving the exact export the patched video paths now call (readProviderJsonResponse).fetch()the body over TCP, then callreadProviderJsonResponse(response, label)with the same labels the patched MiniMax video sites pass.... JSON response exceeds 16777216 bytesand that the client cancelled the socket before the full body was delivered.await response.json()path and confirm it buffers past the 16 MiB cap.Evidence
Original loopback proof:
Refreshed current-head focused regression after adding the
file_idmetadata bound and narrowing this PR to MiniMax video:Known validation note:
node scripts/run-tsgo.mjs -p extensions/minimax/tsconfig.json --incremental falsecurrently fails in existingextensions/minimax/oauth.tsimports fromopenclaw/plugin-sdk/number-runtime; that file is outside this PR's touched surface.Label: security
AI-assisted.
Post-rebase scope note: This PR is video-only and unchanged in intent. The MiniMax image-response bound referenced above as "future work" has since landed on
main, so there is no remaining image hunk here — this PR bounds only the three MiniMax video success/control JSON reads (video-generation-provider.ts: task submit, status poll, andfile_idmetadata).