fix(chutes-oauth-plugin): bound plugin JSON response reads at 16 MiB#96779
Conversation
Replace 2 unbounded (await response.json()) calls in the active bundled plugin path (extensions/chutes/oauth.ts) with readProviderJsonResponse. Sites: fetchChutesUserInfo (userinfo), exchangeChutesCodeForTokens (token exchange). Reuses the existing SDK helper already used by 15+ other providers.
|
Codex review: needs maintainer review before merge. Reviewed June 27, 2026, 5:14 AM ET / 09:14 UTC. Summary PR surface: Source +3, Tests +63. Total +66 across 2 files. Reproducibility: yes. source-reproducible: current main and v2026.6.10 still have raw successful 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:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this narrow plugin-path hardening after maintainer acceptance of the shared Chutes OAuth JSON cap and exact-head gates; review the deprecated core-helper companion separately. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main and v2026.6.10 still have raw successful 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 c5d34c8376f8. Label changesLabel justifications:
Evidence reviewedPR surface: Source +3, Tests +63. Total +66 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
|
|
Upgraded proof: 8 assertions with quantified bytes-sent metrics (hostile body capped at ~16.0 MiB of 32 MiB payload). Added AI disclosure. Marked sibling PR #96777 as companion. @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Co-Authored-By: Claude <[email protected]>
|
Added inline bounded-read regression test (oversized token exchange JSON via ReadableStream, verifies stream cancelled early with bytes-pulled < cap, mock fetchFn pattern matching existing tests). @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Added inline bounded-read regression test (oversized token exchange JSON via ReadableStream, verifies stream cancelled early with bytes-pulled < cap, mock fetchFn pattern matching existing tests). @clawsweeper re-review |
|
@clawsweeper re-review 🦞 upgrades applied (PR body only):
No code changes. |
What Problem This Solves
extensions/chutes/oauth.ts(the active bundled plugin path, entered viaopenclaw onboard --auth-choice chutes) has 2 unboundedawait response.json()calls (userinfo fetch, token exchange). A hostile Chutes endpoint or proxy can return an oversized JSON body that exhausts process memory during the OAuth login flow.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).extensions/chutes/oauth.ts:128,167— replace 2(await response.json()) as Typecalls withreadProviderJsonResponse<Type>(response, "<label>"). Respective labels:"Chutes userinfo","Chutes token exchange".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 is the same pattern used by 15+ bounded-read PRs across the codebase.Why the same 16 MiB cap for both userinfo and token exchange? Both endpoints serve JSON OAuth payloads of comparable size (typically < 1 KiB). Using the same threshold for both avoids introducing a per-endpoint cap distinction with no operational benefit.
Real behavior proof
response.json()calls (userinfo, token exchange) → capped at 16 MiB viareadProviderJsonResponse.node:httpserver (127.0.0.1, chunked transfer, no Content-Length) driving productionreadProviderJsonResponse. Node v22.22.0, Linux x86_64.readProviderJsonResponsethrew canonical overflow at 16 MiB (Chutes userinfo: JSON response exceeds 16777216 bytes). Server sent ~16.0 MiB of a 32 MiB hostile payload — capped before full body. Negative control (small userinfo JSON, login=testuser) and happy path (token exchange, access_token set) parsed correctly.Out of scope
src/agents/chutes-oauth.ts(deprecated core helper) — covered by sibling PR fix(chutes-oauth): bound core helper JSON response reads at 16 MiB #96777.Risk checklist
Diff stats
AI-assisted; reviewed before submission.