Secrets: harden SecretRef-safe models.json persistence (#38955)

This commit is contained in:
Josh Avant
2026-03-07 11:28:39 -06:00
committed by GitHub
parent b08337b902
commit 8e20dd22d8
66 changed files with 2713 additions and 299 deletions

View File

@@ -29,7 +29,10 @@ describe("runCapability deepgram provider options", () => {
deepgram: {
baseUrl: "https://provider.example",
apiKey: "test-key",
headers: { "X-Provider": "1" },
headers: {
"X-Provider": "1",
"X-Provider-Managed": "secretref-managed",
},
models: [],
},
},
@@ -39,7 +42,10 @@ describe("runCapability deepgram provider options", () => {
audio: {
enabled: true,
baseUrl: "https://config.example",
headers: { "X-Config": "2" },
headers: {
"X-Config": "2",
"X-Config-Managed": "secretref-env:DEEPGRAM_HEADER_TOKEN",
},
providerOptions: {
deepgram: {
detect_language: true,
@@ -52,7 +58,10 @@ describe("runCapability deepgram provider options", () => {
provider: "deepgram",
model: "nova-3",
baseUrl: "https://entry.example",
headers: { "X-Entry": "3" },
headers: {
"X-Entry": "3",
"X-Entry-Managed": "secretref-managed",
},
providerOptions: {
deepgram: {
detectLanguage: false,
@@ -79,8 +88,11 @@ describe("runCapability deepgram provider options", () => {
expect(seenBaseUrl).toBe("https://entry.example");
expect(seenHeaders).toMatchObject({
"X-Provider": "1",
"X-Provider-Managed": "secretref-managed",
"X-Config": "2",
"X-Config-Managed": "secretref-env:DEEPGRAM_HEADER_TOKEN",
"X-Entry": "3",
"X-Entry-Managed": "secretref-managed",
});
expect(seenQuery).toMatchObject({
detect_language: false,

View File

@@ -40,6 +40,26 @@ import { estimateBase64Size, resolveVideoMaxBase64Bytes } from "./video.js";
export type ProviderRegistry = Map<string, MediaUnderstandingProvider>;
function sanitizeProviderHeaders(
headers: Record<string, unknown> | undefined,
): Record<string, string> | undefined {
if (!headers) {
return undefined;
}
const next: Record<string, string> = {};
for (const [key, value] of Object.entries(headers)) {
if (typeof value !== "string") {
continue;
}
// Intentionally preserve marker-shaped values here. This path handles
// explicit config/runtime provider headers, where literal values may
// legitimately match marker patterns; discovered models.json entries are
// sanitized separately in the model registry path.
next[key] = value;
}
return Object.keys(next).length > 0 ? next : undefined;
}
function trimOutput(text: string, maxChars?: number): string {
const trimmed = text.trim();
if (!maxChars || trimmed.length <= maxChars) {
@@ -352,9 +372,9 @@ async function resolveProviderExecutionContext(params: {
});
const baseUrl = params.entry.baseUrl ?? params.config?.baseUrl ?? providerConfig?.baseUrl;
const mergedHeaders = {
...providerConfig?.headers,
...params.config?.headers,
...params.entry.headers,
...sanitizeProviderHeaders(providerConfig?.headers as Record<string, unknown> | undefined),
...sanitizeProviderHeaders(params.config?.headers as Record<string, unknown> | undefined),
...sanitizeProviderHeaders(params.entry.headers as Record<string, unknown> | undefined),
};
const headers = Object.keys(mergedHeaders).length > 0 ? mergedHeaders : undefined;
return { apiKeys, baseUrl, headers };