From c2c19a883d668b3b3e21ba518045a48d54c4fad7 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 20 Jun 2026 04:04:40 +0800 Subject: [PATCH] fix(scripts): reject unsafe bounded response lengths Reject unsafe decimal Content-Length values in shared scripts bounded-response helpers before streaming response bodies.\n\nValidation:\n- node --check scripts/lib/bounded-response.mjs\n- direct MJS repro for unsafe Content-Length\n- git diff --check origin/main...HEAD\n- autoreview clean, overall patch correct 0.88\n- exact-head release gate https://github.com/openclaw/openclaw/actions/runs/27845767740 --- scripts/lib/bounded-response.mjs | 2 +- scripts/lib/bounded-response.ts | 2 +- test/scripts/bounded-response.test.ts | 35 +++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/scripts/lib/bounded-response.mjs b/scripts/lib/bounded-response.mjs index adafe8f88ab2..29600386ffd2 100644 --- a/scripts/lib/bounded-response.mjs +++ b/scripts/lib/bounded-response.mjs @@ -19,7 +19,7 @@ function parseContentLengthHeader(headers) { return undefined; } const parsed = Number(raw); - return Number.isSafeInteger(parsed) ? parsed : undefined; + return Number.isSafeInteger(parsed) ? parsed : Number.POSITIVE_INFINITY; } async function readResponseChunk(reader, label, signal, markCanceled) { diff --git a/scripts/lib/bounded-response.ts b/scripts/lib/bounded-response.ts index d50a9f8a5771..6d3d3d66553f 100644 --- a/scripts/lib/bounded-response.ts +++ b/scripts/lib/bounded-response.ts @@ -23,7 +23,7 @@ function parseContentLengthHeader(headers: Headers): number | undefined { return undefined; } const parsed = Number(raw); - return Number.isSafeInteger(parsed) ? parsed : undefined; + return Number.isSafeInteger(parsed) ? parsed : Number.POSITIVE_INFINITY; } async function readResponseChunk( diff --git a/test/scripts/bounded-response.test.ts b/test/scripts/bounded-response.test.ts index 29687949d9c2..bd5c92cbc504 100644 --- a/test/scripts/bounded-response.test.ts +++ b/test/scripts/bounded-response.test.ts @@ -98,4 +98,39 @@ describe("scripts bounded response reader", () => { expect(canceled).toBe(true); }, ); + + it.each(helpers)( + "rejects unsafe decimal %s content-length values before reading", + async (_name, read) => { + let readStarted = false; + let canceled = false; + const response = { + headers: new Headers({ "content-length": "9007199254740993" }), + body: { + async cancel() { + canceled = true; + }, + getReader() { + return { + async read() { + readStarted = true; + return new Promise>(() => {}); + }, + async cancel() { + canceled = true; + }, + releaseLock() {}, + }; + }, + }, + } as unknown as Response; + + await expect(read(response, "probe", 16)).rejects.toThrow( + "probe response body exceeded 16 bytes", + ); + + expect(readStarted).toBe(false); + expect(canceled).toBe(true); + }, + ); });