diff --git a/packages/cli/src/commands/iterate-options.ts b/packages/cli/src/commands/iterate-options.ts index 200575b4..7e1a25fc 100644 --- a/packages/cli/src/commands/iterate-options.ts +++ b/packages/cli/src/commands/iterate-options.ts @@ -1,6 +1,12 @@ import { InvalidArgumentError } from 'commander'; export function parsePositiveSafeInteger(value: string): number { + // Only accept plain decimal digit strings. Number() would otherwise coerce + // scientific ("1e2"), hexadecimal ("0x10"), binary/octal, signed ("+60"), and + // whitespace-padded values into numbers, which are not valid interval inputs. + if (!/^\d+$/.test(value)) { + throw new InvalidArgumentError('must be a positive safe integer'); + } const parsed = Number(value); if (!Number.isSafeInteger(parsed) || parsed < 1) { throw new InvalidArgumentError('must be a positive safe integer'); diff --git a/packages/cli/src/commands/iterate.test.ts b/packages/cli/src/commands/iterate.test.ts index 4892cab6..e9f9011d 100644 --- a/packages/cli/src/commands/iterate.test.ts +++ b/packages/cli/src/commands/iterate.test.ts @@ -12,6 +12,13 @@ describe('parsePositiveSafeInteger', () => { expect(() => parsePositiveSafeInteger(value)).toThrow('positive safe integer'); }, ); + + it.each(['1e2', '0x10', '0b10', '0o10', '+60', ' 60', '60 ', '1_000'])( + 'rejects non-decimal numeric interval %s', + (value) => { + expect(() => parsePositiveSafeInteger(value)).toThrow('positive safe integer'); + }, + ); }); describe('parseQuietHours', () => {