From 7474b52584891e308043db4779ea4549d6325afc Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 18 Apr 2026 18:57:42 +0100 Subject: [PATCH] fix: respect web search SecretRef credentials --- extensions/xai/web-search.test.ts | 4 +- .../web-search-provider-credentials.test.ts | 80 +++++++++++++++++++ .../tools/web-search-provider-credentials.ts | 10 ++- 3 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 src/agents/tools/web-search-provider-credentials.test.ts diff --git a/extensions/xai/web-search.test.ts b/extensions/xai/web-search.test.ts index b9d2208aa08..18176d6d235 100644 --- a/extensions/xai/web-search.test.ts +++ b/extensions/xai/web-search.test.ts @@ -78,8 +78,8 @@ describe("xai web search config resolution", () => { expect(resolveXaiWebSearchModel(searchConfig)).toBe("grok-4-fast"); }); - it("treats unresolved non-env SecretRefs as missing credentials instead of throwing", async () => { - await withEnvAsync({ XAI_API_KEY: undefined }, async () => { + it("treats unresolved non-env SecretRefs as missing credentials instead of using env fallback", async () => { + await withEnvAsync({ XAI_API_KEY: "ambient-xai-test-key" }, async () => { const provider = createXaiWebSearchProvider(); const maybeTool = provider.createTool({ config: { diff --git a/src/agents/tools/web-search-provider-credentials.test.ts b/src/agents/tools/web-search-provider-credentials.test.ts new file mode 100644 index 00000000000..9de7e58c3a6 --- /dev/null +++ b/src/agents/tools/web-search-provider-credentials.test.ts @@ -0,0 +1,80 @@ +import { describe, expect, it } from "vitest"; +import { withEnv } from "../../test-utils/env.js"; +import { resolveWebSearchProviderCredential } from "./web-search-provider-credentials.js"; + +describe("resolveWebSearchProviderCredential", () => { + it("uses configured literal credentials before ambient env fallback", () => { + withEnv({ TEST_WEB_SEARCH_KEY: "ambient-test-value" }, () => { + expect( + resolveWebSearchProviderCredential({ + credentialValue: "configured-test-value", + path: "tools.web.search.provider.apiKey", + envVars: ["TEST_WEB_SEARCH_KEY"], + }), + ).toBe("configured-test-value"); + }); + }); + + it("resolves configured env SecretRefs", () => { + withEnv({ TEST_WEB_SEARCH_REF_KEY: "ref-test-value" }, () => { + expect( + resolveWebSearchProviderCredential({ + credentialValue: { + source: "env", + provider: "default", + id: "TEST_WEB_SEARCH_REF_KEY", + }, + path: "tools.web.search.provider.apiKey", + envVars: ["TEST_WEB_SEARCH_KEY"], + }), + ).toBe("ref-test-value"); + }); + }); + + it("does not override missing env SecretRefs with ambient env fallback", () => { + withEnv( + { TEST_WEB_SEARCH_REF_KEY: undefined, TEST_WEB_SEARCH_KEY: "ambient-test-value" }, + () => { + expect( + resolveWebSearchProviderCredential({ + credentialValue: { + source: "env", + provider: "default", + id: "TEST_WEB_SEARCH_REF_KEY", + }, + path: "tools.web.search.provider.apiKey", + envVars: ["TEST_WEB_SEARCH_KEY"], + }), + ).toBeUndefined(); + }, + ); + }); + + it("does not override non-env SecretRefs with ambient env fallback", () => { + withEnv({ TEST_WEB_SEARCH_KEY: "ambient-test-value" }, () => { + expect( + resolveWebSearchProviderCredential({ + credentialValue: { + source: "file", + provider: "vault", + id: "/providers/web-search/api-key", + }, + path: "tools.web.search.provider.apiKey", + envVars: ["TEST_WEB_SEARCH_KEY"], + }), + ).toBeUndefined(); + }); + }); + + it("falls back to ambient env when no credential is configured", () => { + withEnv({ TEST_WEB_SEARCH_KEY: "ambient-test-value" }, () => { + expect( + resolveWebSearchProviderCredential({ + credentialValue: undefined, + path: "tools.web.search.provider.apiKey", + envVars: ["TEST_WEB_SEARCH_KEY"], + }), + ).toBe("ambient-test-value"); + }); + }); +}); diff --git a/src/agents/tools/web-search-provider-credentials.ts b/src/agents/tools/web-search-provider-credentials.ts index dfe7ca63557..f1c4f932860 100644 --- a/src/agents/tools/web-search-provider-credentials.ts +++ b/src/agents/tools/web-search-provider-credentials.ts @@ -12,14 +12,16 @@ export function resolveWebSearchProviderCredential(params: { return fromConfig; } - const credentialRef = resolveSecretInputRef({ - value: params.credentialValue, - }).ref; - if (credentialRef?.source === "env") { + const credentialRef = resolveSecretInputRef({ value: params.credentialValue }).ref; + if (credentialRef) { + if (credentialRef.source !== "env") { + return undefined; + } const fromEnvRef = normalizeSecretInput(process.env[credentialRef.id]); if (fromEnvRef) { return fromEnvRef; } + return undefined; } for (const envVar of params.envVars) {