fix(config): preserve passwordFile whitelist exemption

This commit is contained in:
Gustavo Madeira Santana
2026-02-15 10:10:28 -05:00
parent 7050a2e001
commit 2d9a323714
3 changed files with 22 additions and 8 deletions

View File

@@ -11,6 +11,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Subagents/Models: preserve `agents.defaults.model.fallbacks` when subagent sessions carry a model override, so subagent runs fail over to configured fallback models instead of retrying only the overridden primary model.
- Config/Gateway: make sensitive-key whitelist suffix matching case-insensitive while preserving `passwordFile` path exemptions, preventing accidental redaction of non-secret config values like `maxTokens` and IRC password-file paths. (#16042) Thanks @akramcodez.
- Group chats: always inject group chat context (name, participants, reply guidance) into the system prompt on every turn, not just the first. Prevents the model from losing awareness of which group it's in and incorrectly using the message tool to send to the same group. (#14447) Thanks @tyler6204.
- TUI: make searchable-select filtering and highlight rendering ANSI-aware so queries ignore hidden escape codes and no longer corrupt ANSI styling sequences during match highlighting. (#4519) Thanks @bee4come.
- TUI/Windows: coalesce rapid single-line submit bursts in Git Bash into one multiline message as a fallback when bracketed paste is unavailable, preventing pasted multiline text from being split into multiple sends. (#4986) Thanks @adamkane.

View File

@@ -1,11 +1,26 @@
import { describe, expect, it } from "vitest";
import { z } from "zod";
import { __test__ } from "./schema.hints.js";
import { __test__, isSensitiveConfigPath } from "./schema.hints.js";
import { OpenClawSchema } from "./zod-schema.js";
import { sensitive } from "./zod-schema.sensitive.js";
const { mapSensitivePaths } = __test__;
describe("isSensitiveConfigPath", () => {
it("matches whitelist suffixes case-insensitively", () => {
expect(isSensitiveConfigPath("maxTokens")).toBe(false);
expect(isSensitiveConfigPath("MAXTOKENS")).toBe(false);
expect(isSensitiveConfigPath("channels.irc.nickserv.passwordFile")).toBe(false);
expect(isSensitiveConfigPath("channels.irc.nickserv.PASSWORDFILE")).toBe(false);
});
it("keeps true sensitive keys redacted", () => {
expect(isSensitiveConfigPath("channels.slack.token")).toBe(true);
expect(isSensitiveConfigPath("models.providers.openai.apiKey")).toBe(true);
expect(isSensitiveConfigPath("channels.irc.nickserv.password")).toBe(true);
});
});
describe("mapSensitivePaths", () => {
it("should detect sensitive fields nested inside all structural Zod types", () => {
const GrandSchema = z.object({

View File

@@ -91,7 +91,7 @@ const FIELD_PLACEHOLDERS: Record<string, string> = {
* These are explicitly excluded from redaction (plugin config) and
* warnings about not being marked sensitive (base config).
*/
const SENSITIVE_KEY_WHITELIST = new Set([
const SENSITIVE_KEY_WHITELIST_SUFFIXES = [
"maxtokens",
"maxoutputtokens",
"maxinputtokens",
@@ -101,17 +101,15 @@ const SENSITIVE_KEY_WHITELIST = new Set([
"tokencount",
"tokenlimit",
"tokenbudget",
"passwordFile",
]);
"passwordfile",
] as const;
const SENSITIVE_PATTERNS = [/token$/i, /password/i, /secret/i, /api.?key/i];
export function isSensitiveConfigPath(path: string): boolean {
const lowerPath = path.toLowerCase();
return (
!Array.from(SENSITIVE_KEY_WHITELIST).some((suffix) => lowerPath.endsWith(suffix)) &&
SENSITIVE_PATTERNS.some((pattern) => pattern.test(path))
);
const whitelisted = SENSITIVE_KEY_WHITELIST_SUFFIXES.some((suffix) => lowerPath.endsWith(suffix));
return !whitelisted && SENSITIVE_PATTERNS.some((pattern) => pattern.test(path));
}
export function buildBaseHints(): ConfigUiHints {