fix(e2e): reject unsafe chat tools body lengths

Reject unsafe numeric Content-Length values in the OpenAI chat tools E2E client before waiting on the response stream.

Also hardens Docker E2E heartbeat timing coverage after the exact-head release gate exposed a brittle zero-padded heartbeat assertion.

Verification: direct mock gateway repro, docker heartbeat shell proof, autoreview clean, and exact-head CI release gate https://github.com/openclaw/openclaw/actions/runs/27843455246.
This commit is contained in:
Vincent Koc
2026-06-20 03:09:51 +08:00
committed by GitHub
parent 061a3705db
commit 6cfb025143
3 changed files with 30 additions and 17 deletions

View File

@@ -51,7 +51,7 @@ async function readBoundedResponseText(response, byteLimit, timeoutPromise) {
const contentLength = response.headers?.get?.("content-length");
if (contentLength && /^\d+$/u.test(contentLength)) {
const parsedContentLength = Number(contentLength);
if (Number.isSafeInteger(parsedContentLength) && parsedContentLength > byteLimit) {
if (!Number.isSafeInteger(parsedContentLength) || parsedContentLength > byteLimit) {
await response.body?.cancel().catch(() => undefined);
throw new Error(`chat completions response body exceeded ${byteLimit} bytes`);
}

View File

@@ -3020,7 +3020,7 @@ export ROOT_DIR TMPDIR
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
output="$(run_logged_print_heartbeat plugins-run 1 bash -c 'printf "captured container log\\\\n"; /bin/sleep 2')"
output="$(run_logged_print_heartbeat plugins-run 1 bash -c 'printf "captured container log\\\\n"; /bin/sleep 4')"
[[ "$output" = *"still running plugins-run ("* ]]
[[ "$output" = *"log bytes captured"* ]]
[[ "$output" = *"captured container log"* ]]
@@ -3195,28 +3195,18 @@ output="$(run_logged_print_heartbeat plugins-run 30 bash -c 'printf "quick conta
});
it("normalizes zero-padded Docker E2E log heartbeat intervals", () => {
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-e2e-log-zero-heartbeat-"));
try {
const rootDir = process.cwd();
const script = `
const rootDir = process.cwd();
const script = `
set -euo pipefail
ROOT_DIR=${shellQuote(rootDir)}
TMPDIR=${shellQuote(workDir)}
export ROOT_DIR TMPDIR
export ROOT_DIR
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
output="$(run_logged_print_heartbeat plugins-run 08 bash -c 'printf "captured container log\\\\n"; /bin/sleep 9')"
[[ "$output" = *"still running plugins-run (8s elapsed,"* ]]
[[ "$output" = *"log bytes captured"* ]]
[[ "$output" = *"captured container log"* ]]
[[ "$(docker_e2e_normalize_positive_int_value 'Docker E2E log heartbeat interval' 08)" = "8" ]]
`;
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
} finally {
rmSync(workDir, { recursive: true, force: true });
}
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
});
it("normalizes zero-padded Docker E2E stats heartbeat intervals", () => {

View File

@@ -404,4 +404,27 @@ describe("scripts/e2e/lib/openai-chat-tools/client.mjs", () => {
server.close();
}
});
it("rejects unsafe declared chat completion body lengths before waiting on the stream", async () => {
const server = createServer((_request, response) => {
response.writeHead(200, {
"content-length": "9007199254740993",
"content-type": "application/json",
});
response.flushHeaders();
});
const port = await listen(server);
try {
const startedAt = Date.now();
const result = await runClient(port, { OPENCLAW_OPENAI_CHAT_TOOLS_MAX_BODY_BYTES: "64" });
expect(result.error).toBeUndefined();
expect(result.status).not.toBe(0);
expect(result.stderr).toContain("chat completions response body exceeded 64 bytes");
expect(result.stderr).not.toContain("timed out");
expect(Date.now() - startedAt).toBeLessThan(3_500);
} finally {
server.close();
}
});
});