From dd46fd36a3ca6c0e752769ce802babf7d2e9aa6b Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Wed, 3 Jun 2026 01:59:48 +0200 Subject: [PATCH] fix(tooling): reject malformed cross-os release timeouts --- scripts/openclaw-cross-os-release-checks.ts | 7 +++++-- .../openclaw-cross-os-release-checks.test.ts | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/scripts/openclaw-cross-os-release-checks.ts b/scripts/openclaw-cross-os-release-checks.ts index 20751d474dd..765cb26856f 100644 --- a/scripts/openclaw-cross-os-release-checks.ts +++ b/scripts/openclaw-cross-os-release-checks.ts @@ -204,11 +204,14 @@ export function parseArgs(argv) { return parsed; } -function parsePositiveIntegerEnv(name, fallback) { - const raw = process.env[name]?.trim(); +export function parsePositiveIntegerEnv(name, fallback, env = process.env) { + const raw = env[name]?.trim(); if (!raw) { return fallback; } + if (!/^\d+$/u.test(raw)) { + throw new Error(`${name} must be a positive integer. Got: ${JSON.stringify(raw)}`); + } const value = Number(raw); if (!Number.isSafeInteger(value) || value <= 0) { throw new Error(`${name} must be a positive integer. Got: ${JSON.stringify(raw)}`); diff --git a/test/scripts/openclaw-cross-os-release-checks.test.ts b/test/scripts/openclaw-cross-os-release-checks.test.ts index afed895f3f4..4c88b86d237 100644 --- a/test/scripts/openclaw-cross-os-release-checks.test.ts +++ b/test/scripts/openclaw-cross-os-release-checks.test.ts @@ -51,6 +51,7 @@ import { normalizeWindowsCommandShimPath, normalizeWindowsInstalledCliPath, maybeBuildOptionalAgentTurnSkipResult, + parsePositiveIntegerEnv, parseCrossOsSuiteFilter, parseArgs, packageHasScript, @@ -202,6 +203,25 @@ describe("scripts/openclaw-cross-os-release-checks", () => { expect(CROSS_OS_COMMAND_HEARTBEAT_SECONDS).toBeLessThanOrEqual(60); }); + it("rejects malformed cross-OS positive integer environment values", () => { + expect(parsePositiveIntegerEnv("OPENCLAW_CROSS_OS_COMMAND_HEARTBEAT_SECONDS", 60, {})).toBe( + 60, + ); + expect( + parsePositiveIntegerEnv("OPENCLAW_CROSS_OS_COMMAND_HEARTBEAT_SECONDS", 60, { + OPENCLAW_CROSS_OS_COMMAND_HEARTBEAT_SECONDS: "25", + }), + ).toBe(25); + + for (const raw of ["1e3", "25ms", "1.5", "0", "-1", String(Number.MAX_SAFE_INTEGER + 1)]) { + expect(() => + parsePositiveIntegerEnv("OPENCLAW_CROSS_OS_COMMAND_HEARTBEAT_SECONDS", 60, { + OPENCLAW_CROSS_OS_COMMAND_HEARTBEAT_SECONDS: raw, + }), + ).toThrow("OPENCLAW_CROSS_OS_COMMAND_HEARTBEAT_SECONDS must be a positive integer"); + } + }); + it("records packaged-fresh phase timings for release-check summaries", () => { const source = readFileSync("scripts/openclaw-cross-os-release-checks.ts", "utf8"); const freshLaneSource = source.slice(