From e67ff0c43e08dea4f8d35ceca98a3ffe79cd8f8d Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 28 May 2026 12:02:21 -0400 Subject: [PATCH] fix: canonicalize secret target array indexes --- src/secrets/target-registry-pattern.test.ts | 21 +++++++++++++++++++++ src/secrets/target-registry-pattern.ts | 5 +++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/secrets/target-registry-pattern.test.ts b/src/secrets/target-registry-pattern.test.ts index 2cd3537fb53..908060c0c01 100644 --- a/src/secrets/target-registry-pattern.test.ts +++ b/src/secrets/target-registry-pattern.test.ts @@ -23,6 +23,24 @@ describe("target registry pattern helpers", () => { tokens, ), ).toBeNull(); + expect( + matchPathTokens( + ["agents", "list", "02", "memorySearch", "providers", "openai", "apiKey"], + tokens, + ), + ).toBeNull(); + expect( + matchPathTokens( + ["agents", "list", "+2", "memorySearch", "providers", "openai", "apiKey"], + tokens, + ), + ).toBeNull(); + expect( + matchPathTokens( + ["agents", "list", "4294967294", "memorySearch", "providers", "openai", "apiKey"], + tokens, + ), + ).toBeNull(); }); it("materializes sibling ref paths from wildcard and array captures", () => { @@ -37,6 +55,9 @@ describe("target registry pattern helpers", () => { "apiKeyRef", ]); expect(materializePathTokens(refTokens, ["anthropic"])).toBeNull(); + expect(materializePathTokens(refTokens, ["01", "anthropic"])).toBeNull(); + expect(materializePathTokens(refTokens, ["+1", "anthropic"])).toBeNull(); + expect(materializePathTokens(refTokens, ["4294967294", "anthropic"])).toBeNull(); }); it("matches two wildcard captures in five-segment header paths", () => { diff --git a/src/secrets/target-registry-pattern.ts b/src/secrets/target-registry-pattern.ts index 0504c3023e0..fc32eb5f7dd 100644 --- a/src/secrets/target-registry-pattern.ts +++ b/src/secrets/target-registry-pattern.ts @@ -1,3 +1,4 @@ +import { parseConfigPathArrayIndex } from "../shared/path-array-index.js"; import { isRecord, parseDotPath } from "./shared.js"; import type { SecretTargetRegistryEntry } from "./target-registry-types.js"; @@ -92,7 +93,7 @@ export function matchPathTokens( return null; } const next = segments[index + 1]; - if (!next || !/^\d+$/.test(next)) { + if (!next || parseConfigPathArrayIndex(next) === undefined) { return null; } captures.push(next); @@ -122,7 +123,7 @@ export function materializePathTokens( continue; } const arrayIndex = captures[captureIndex]; - if (!arrayIndex || !/^\d+$/.test(arrayIndex)) { + if (!arrayIndex || parseConfigPathArrayIndex(arrayIndex) === undefined) { return null; } out.push(token.field, arrayIndex);