fix(e2e): reject unsafe bounded response text lengths

Reject unsafe decimal Content-Length values in the E2E bounded response text helper before streaming response bodies. Keep non-decimal values on the streaming byte-limit path and add regression coverage proving unsafe declared lengths cancel without starting a read.

Proof: direct patched repro rejects before reading with code ETOOBIG; origin/main comparison entered the reader first; node --check scripts/e2e/lib/bounded-response-text.mjs; git diff --check origin/main...HEAD; autoreview clean overall 0.86; exact-head release gate succeeded at https://github.com/openclaw/openclaw/actions/runs/27846197115.
This commit is contained in:
Vincent Koc
2026-06-20 04:20:02 +08:00
committed by GitHub
parent 9594300f8c
commit 0f18e82932
2 changed files with 33 additions and 1 deletions

View File

@@ -17,7 +17,7 @@ function parseContentLengthHeader(headers) {
return undefined;
}
const parsed = Number(raw);
return Number.isSafeInteger(parsed) ? parsed : undefined;
return Number.isSafeInteger(parsed) ? parsed : Number.POSITIVE_INFINITY;
}
export async function readBoundedResponseText(response, label, byteLimit, timeoutPromise) {

View File

@@ -111,4 +111,36 @@ describe("scripts/e2e/lib/bounded-response-text.mjs", () => {
expect(readStarted).toBe(true);
expect(canceled).toBe(true);
});
it("rejects unsafe decimal content-length values before reading", async () => {
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<ReadableStreamReadResult<Uint8Array>>(() => {});
},
async cancel() {
canceled = true;
},
releaseLock() {},
};
},
},
};
await expect(readBoundedResponseText(response, "probe", 16)).rejects.toMatchObject({
code: "ETOOBIG",
message: "probe response body exceeded 16 bytes",
});
expect(readStarted).toBe(false);
expect(canceled).toBe(true);
});
});