From: Jérôme Benoit Date: Wed, 15 Apr 2026 20:15:42 +0000 (+0200) Subject: fix(cli): validate connect timeout budget — reject NaN/0/negative before race X-Git-Tag: cli@v4.5.0~83 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=99fc323675d2cab228ea5d83064365bd75842166;p=e-mobility-charging-stations-simulator.git fix(cli): validate connect timeout budget — reject NaN/0/negative before race --- diff --git a/ui/cli/src/client/lifecycle.ts b/ui/cli/src/client/lifecycle.ts index bf1f69e7..00fc1093 100644 --- a/ui/cli/src/client/lifecycle.ts +++ b/ui/cli/src/client/lifecycle.ts @@ -46,6 +46,9 @@ export const executeCommand = async (options: ExecuteOptions): Promise => activeClient = client const budget = timeoutMs ?? UI_WEBSOCKET_REQUEST_TIMEOUT_MS + if (!Number.isFinite(budget) || budget <= 0) { + throw new Error(`Invalid timeout: ${String(budget)}ms (must be > 0)`) + } const startTime = Date.now() let connectTimeoutId: ReturnType | undefined diff --git a/ui/cli/tests/lifecycle.test.ts b/ui/cli/tests/lifecycle.test.ts index a8ca7aa4..d5f4a4ad 100644 --- a/ui/cli/tests/lifecycle.test.ts +++ b/ui/cli/tests/lifecycle.test.ts @@ -34,4 +34,21 @@ await describe('lifecycle', async () => { await it('should export executeCommand function', () => { assert.strictEqual(typeof executeCommand, 'function') }) + + await it('should reject executeCommand with NaN timeout', async () => { + await assert.rejects( + executeCommand({ + config: { host: 'localhost', port: 8080, protocol: 'ui', version: '0.0.1' }, + formatter: { error: () => undefined, output: () => undefined }, + payload: {}, + procedureName: 'listChargingStations' as never, + timeoutMs: Number.NaN, + }), + (error: Error) => { + assert.ok(error.message.includes('Invalid timeout')) + assert.ok(error.message.includes('NaN')) + return true + } + ) + }) })