Config: add secret ref schema and redaction foundations

This commit is contained in:
joshavant
2026-02-21 10:55:17 -08:00
committed by Peter Steinberger
parent 6daf40d3f4
commit c3a4251a60
12 changed files with 253 additions and 8 deletions

View File

@@ -17,6 +17,39 @@ function isEnvVarPlaceholder(value: string): boolean {
return ENV_VAR_PLACEHOLDER_PATTERN.test(value.trim());
}
function isWholeObjectSensitivePath(path: string): boolean {
const lowered = path.toLowerCase();
return lowered.endsWith("serviceaccount") || lowered.endsWith("serviceaccountref");
}
function collectSensitiveStrings(value: unknown, values: string[]): void {
if (typeof value === "string") {
if (!isEnvVarPlaceholder(value)) {
values.push(value);
}
return;
}
if (Array.isArray(value)) {
for (const item of value) {
collectSensitiveStrings(item, values);
}
return;
}
if (value && typeof value === "object") {
for (const item of Object.values(value as Record<string, unknown>)) {
collectSensitiveStrings(item, values);
}
}
}
function isExtensionPath(path: string): boolean {
return (
path === "plugins" ||
path.startsWith("plugins.") ||
path === "channels" ||
path.startsWith("channels.")
);
}
function isExplicitlyNonSensitivePath(hints: ConfigUiHints | undefined, paths: string[]): boolean {
if (!hints) {
return false;
@@ -149,7 +182,19 @@ function redactObjectWithLookup(
result[key] = REDACTED_SENTINEL;
values.push(value);
} else if (typeof value === "object" && value !== null) {
result[key] = redactObjectWithLookup(value, lookup, candidate, values, hints);
if (hints[candidate]?.sensitive === true && !Array.isArray(value)) {
collectSensitiveStrings(value, values);
result[key] = REDACTED_SENTINEL;
} else {
result[key] = redactObjectWithLookup(value, lookup, candidate, values, hints);
}
} else if (
hints[candidate]?.sensitive === true &&
value !== undefined &&
value !== null
) {
// Keep primitives at explicitly-sensitive paths fully redacted.
result[key] = REDACTED_SENTINEL;
}
break;
}
@@ -221,6 +266,16 @@ function redactObjectGuessing(
) {
result[key] = REDACTED_SENTINEL;
values.push(value);
} else if (
!isExplicitlyNonSensitivePath(hints, [dotPath, wildcardPath]) &&
isSensitivePath(dotPath) &&
isWholeObjectSensitivePath(dotPath) &&
value &&
typeof value === "object" &&
!Array.isArray(value)
) {
collectSensitiveStrings(value, values);
result[key] = REDACTED_SENTINEL;
} else if (typeof value === "object" && value !== null) {
result[key] = redactObjectGuessing(value, dotPath, values, hints);
} else {