From 9cdcdf3dff3118f13f667f04ffab9e3eefe7c3a7 Mon Sep 17 00:00:00 2001 From: RRFZ <247457381+Plastic-time@users.noreply.github.com> Date: Fri, 6 Nov 2026 12:28:12 -0500 Subject: [PATCH] fix(cli): reject non-decimal guidance search limits (#9165) --- src/cli/guidanceCommands.ts | 8 +++++--- tests/boundary/cli/guidanceCli.test.ts | 7 +++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/cli/guidanceCommands.ts b/src/cli/guidanceCommands.ts index 34486f309b..6758d93bf7 100644 --- a/src/cli/guidanceCommands.ts +++ b/src/cli/guidanceCommands.ts @@ -14,6 +14,7 @@ import { logCliCommand } from "../cliLogging.js"; import { projectAnalysisError } from "../domain/analysisErrorProjection.js"; import type { Logger } from "pino"; import type { CliInstance } from "./types.js"; +import { cliDecimalField } from "./options.js"; /** Guidance descriptors owned by one CLI host. */ export class CliGuidanceResources { @@ -64,9 +65,10 @@ export const registerGuidanceCommands = ( locator: readGuidanceSectionInputSchema.shape.locator .optional() .describe("Required with --action read; locator returned by search"), - limit: searchGuidanceLimitSchema - .optional() - .describe("Maximum search matches; search only, defaults to 8"), + // Decimal tokens only: numeric coercion would read "0x2" as 2. + limit: cliDecimalField(searchGuidanceLimitSchema.optional()).describe( + "Maximum search matches; search only, defaults to 8", + ), cursor: searchGuidanceInputSchema.shape.cursor .optional() .describe("Continue a search page; search only"), diff --git a/tests/boundary/cli/guidanceCli.test.ts b/tests/boundary/cli/guidanceCli.test.ts index f169bd17eb..bb51ca6002 100644 --- a/tests/boundary/cli/guidanceCli.test.ts +++ b/tests/boundary/cli/guidanceCli.test.ts @@ -75,6 +75,13 @@ it("reports no matches and rejects invalid CLI inputs", async () => { }); const empty = await run(["guidance", "--query", " "]); expect(empty.exitCode).not.toBe(0); + // Numeric coercion would read "0x2" as a two-match page. + const hexLimit = await run(["guidance", "--query", "module", "--limit=0x2"]); + expect(hexLimit.exitCode).not.toBe(0); + expect(JSON.parse(hexLimit.stdout)).toMatchObject({ + code: "VALIDATION_ERROR", + fieldErrors: [expect.objectContaining({ path: "limit" })], + }); const malformed = await run([ "guidance", "--action",