test(provider-usage): cover bounded shared response reads#96360
Conversation
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. Keep open: the runtime provider-usage bounded-read fix is already on current main, but this PR now contains focused shared-helper regression tests that are not on main and are still useful. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Canonical path: Close this PR as superseded by #97659. So I’m closing this here and keeping the remaining discussion on #97659. Review detailsBest possible solution: Close this PR as superseded by #97659. Do we have a high-confidence way to reproduce the issue? Yes, but not as a current-main failure: current main already has the runtime fix. The oversized-stream behavior is source-proven through Is this the best way to solve the issue? Yes. After the runtime fix moved to main, focused shared-helper regression coverage is the narrowest maintainable remaining solution; reintroducing the older runtime diff would create drift. Security review: Security review cleared: The diff is test-only and adds no dependencies, workflows, secrets handling, package resolution, or executable supply-chain surface. AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model internal, reasoning high; reviewed against db2786bde105. |
dbc8341 to
24c8d08
Compare
Co-authored-by: solodmd <[email protected]>
24c8d08 to
afe42ee
Compare
|
Maintainer update: rebased this PR onto current main and narrowed it to the still-useful shared The runtime implementation already landed through #97659 as db2786b, using the shared Validation run locally:
|
What Problem This Solves
readUsageJsoninsrc/infra/provider-usage.fetch.shared.tsreads providerusage API responses with an unbounded
await response.json(). Acompromised or hijacked provider endpoint can stream an arbitrarily large
body and force the runtime to buffer the entire payload before parsing —
an OOM/DoS vector. This is the same vulnerability class already hardened
for OpenRouter (#95420), Google (#95417), provider HTTP errors (#95218),
Matrix (#95240), and ClawHub (#95226); the provider usage monitoring path
was still reading without a cap.
Changes
src/infra/provider-usage.fetch.shared.ts— importreadResponseWithLimitfrom@openclaw/media-core/read-response-with-limit; replaceawait response.json()withreadResponseWithLimitat 16 MiB cap +JSON.parse(new TextDecoder().decode(buffer)). UsesTextDecoder(notBuffer.toString) to preserve UTF-8 BOM stripping semantics thatresponse.json()provides, matching the sibling bounded-read pattern inprovider-http-errors.ts:308.Evidence
Real behavior proof
A ReadableStream enqueues a single 16777217 byte chunk (just over the 16 MiB
cap) into a Response body.
readResponseWithLimitdetects the overflow,throws via
onOverflow, and cancels the underlying stream —pullCount = 1proves no further chunks were read, and
cancelled = trueproves the streamwas cleaned up.
Tests
rejects an oversized JSON responsecreates aReadableStream whose first chunk exceeds the 16 MiB cap and proves the
bounded read cancels the body (
cancelcalled once,pullcount ≤ 2)and returns
{ ok: false, snapshot: { error: "Malformed usage response" } }.parses a normal-sized JSON responseproves a validresponse under the cap returns
{ ok: true, data }unchanged.handles a JSON parse error gracefullyprovesnon-JSON content still returns
"Malformed usage response"via the catchblock.
pnpm test src/infra/provider-usage.fetch.shared.test.ts→ 16 passed (16)oxlinton the changed file → exit 0, no findings