diff --git a/extensions/onepassword/src/cli.test.ts b/extensions/onepassword/src/cli.test.ts index 4c61bfa02dc7..0761dc35afcd 100644 --- a/extensions/onepassword/src/cli.test.ts +++ b/extensions/onepassword/src/cli.test.ts @@ -160,4 +160,27 @@ describe("1Password CLI output", () => { `${"x".repeat(76)}...`, ]); }); + + it.each(["", "0", "-1", "1.5", "0x10", "1e3", "1001"])( + "rejects invalid audit limits: %j", + async (limit) => { + const store = new MemoryKeyedStore(); + const entries = vi.spyOn(store, "entries"); + const { onepassword, write } = setupCommands(store); + + await expect(onepassword.child("audit").run({ limit })).rejects.toThrow( + "--limit must be an integer from 1 to 1000", + ); + expect(entries).not.toHaveBeenCalled(); + expect(write).not.toHaveBeenCalled(); + }, + ); + + it("accepts the maximum decimal audit limit", async () => { + const { onepassword, write } = setupCommands(); + + await onepassword.child("audit").run({ limit: "1000" }); + + expect(JSON.parse(String(write.mock.calls[0]?.[0]))).toEqual([]); + }); }); diff --git a/extensions/onepassword/src/cli.ts b/extensions/onepassword/src/cli.ts index 858a9d039b4f..73e8d85da257 100644 --- a/extensions/onepassword/src/cli.ts +++ b/extensions/onepassword/src/cli.ts @@ -1,3 +1,4 @@ +import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime"; import type { PluginStateKeyedStore } from "openclaw/plugin-sdk/plugin-state-runtime"; import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime"; import type { AuditRow } from "./broker.js"; @@ -23,8 +24,8 @@ function parseLimit(value: unknown): number { if (value === undefined) { return 50; } - const parsed = typeof value === "string" ? Number(value) : Number.NaN; - if (!Number.isInteger(parsed) || parsed < 1 || parsed > 1000) { + const parsed = parseStrictPositiveInteger(value); + if (parsed === undefined || parsed > 1000) { throw new Error("--limit must be an integer from 1 to 1000"); } return parsed;