From be8b852b9d69b3aeeaa06ef45f272b52485e2cec Mon Sep 17 00:00:00 2001 From: jovial_liu Date: Fri, 12 Jun 2026 00:09:59 +0800 Subject: [PATCH] cli: validate logs tail argument --- packages/cli/src/commands/logs.ts | 9 ++++-- src/__tests__/cli-logs.test.ts | 50 +++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/__tests__/cli-logs.test.ts diff --git a/packages/cli/src/commands/logs.ts b/packages/cli/src/commands/logs.ts index 8608b867..bf6d8ce2 100644 --- a/packages/cli/src/commands/logs.ts +++ b/packages/cli/src/commands/logs.ts @@ -13,8 +13,13 @@ const accent = chalk.rgb(131, 127, 255); const args = process.argv.slice(3); let limit = 20; const tailIdx = args.indexOf("--tail"); -if (tailIdx !== -1 && args[tailIdx + 1]) { - limit = parseInt(args[tailIdx + 1], 10) || 20; +if (tailIdx !== -1) { + const rawLimit = args[tailIdx + 1]; + if (!rawLimit || !/^\d+$/.test(rawLimit) || Number(rawLimit) < 1) { + console.log(chalk.red("Invalid --tail value. Expected a positive integer.")); + process.exit(1); + } + limit = Number(rawLimit); } const config = loadConfig(); diff --git a/src/__tests__/cli-logs.test.ts b/src/__tests__/cli-logs.test.ts new file mode 100644 index 00000000..79770c80 --- /dev/null +++ b/src/__tests__/cli-logs.test.ts @@ -0,0 +1,50 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +const originalArgv = process.argv.slice(); +const originalExit = process.exit; + +describe("automaton-cli logs validation", () => { + beforeEach(() => { + vi.resetModules(); + vi.clearAllMocks(); + }); + + afterEach(() => { + process.argv = originalArgv.slice(); + process.exit = originalExit; + vi.restoreAllMocks(); + vi.resetModules(); + }); + + it.each(["0", "-1", "abc"])("rejects invalid --tail value %s", async (value) => { + const logSpy = vi.spyOn(console, "log").mockImplementation(() => {}); + const exitSpy = vi + .spyOn(process, "exit") + .mockImplementation(((code?: number) => { + throw new Error(`process.exit:${code ?? 0}`); + }) as typeof process.exit); + + process.argv = ["node", "automaton-cli", "logs", "--tail", value]; + + await expect(import("../../packages/cli/src/commands/logs.ts")).rejects.toThrow("process.exit:1"); + + expect(exitSpy).toHaveBeenCalledWith(1); + expect(logSpy).toHaveBeenCalledWith("Invalid --tail value. Expected a positive integer."); + }); + + it("rejects missing --tail value", async () => { + const logSpy = vi.spyOn(console, "log").mockImplementation(() => {}); + const exitSpy = vi + .spyOn(process, "exit") + .mockImplementation(((code?: number) => { + throw new Error(`process.exit:${code ?? 0}`); + }) as typeof process.exit); + + process.argv = ["node", "automaton-cli", "logs", "--tail"]; + + await expect(import("../../packages/cli/src/commands/logs.ts")).rejects.toThrow("process.exit:1"); + + expect(exitSpy).toHaveBeenCalledWith(1); + expect(logSpy).toHaveBeenCalledWith("Invalid --tail value. Expected a positive integer."); + }); +});