fix(config): avoid redacting maxTokens-like fields (#14006)

* fix(config): avoid redacting maxTokens-like fields

* fix(config): finalize redaction prep items (#14006) (thanks @constansino)

---------

Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
This commit is contained in:
constansino
2026-02-11 05:32:00 -08:00
committed by GitHub
parent 851fcb2617
commit 66ca5746ce
5 changed files with 38 additions and 3 deletions

View File

@@ -8,6 +8,7 @@ Docs: https://docs.openclaw.ai
- Version alignment: bump manifests and package versions to `2026.2.10`; keep `appcast.xml` unchanged until the next macOS release cut.
- CLI: add `openclaw logs --local-time` (plus `--localTime` compatibility alias) to display log timestamps in local timezone. (#13818) Thanks @xialonglee.
- Config: avoid redacting `maxTokens`-like fields during config snapshot redaction, preventing round-trip validation failures in `/config`. (#14006) Thanks @constansino.
## 2026.2.9

View File

@@ -109,6 +109,40 @@ describe("redactConfigSnapshot", () => {
expect(result.config).toEqual(snapshot.config);
});
it("does not redact maxTokens-style fields", () => {
const snapshot = makeSnapshot({
models: {
providers: {
openai: {
models: [
{
id: "gpt-5",
maxTokens: 65536,
contextTokens: 200000,
maxTokensField: "max_completion_tokens",
},
],
apiKey: "sk-proj-abcdef1234567890ghij",
accessToken: "access-token-value-1234567890",
},
},
},
});
const result = redactConfigSnapshot(snapshot);
const models = result.config.models as Record<string, unknown>;
const providerList = ((
(models.providers as Record<string, unknown>).openai as Record<string, unknown>
).models ?? []) as Array<Record<string, unknown>>;
expect(providerList[0]?.maxTokens).toBe(65536);
expect(providerList[0]?.contextTokens).toBe(200000);
expect(providerList[0]?.maxTokensField).toBe("max_completion_tokens");
const providers = (models.providers as Record<string, Record<string, string>>) ?? {};
expect(providers.openai.apiKey).toBe(REDACTED_SENTINEL);
expect(providers.openai.accessToken).toBe(REDACTED_SENTINEL);
});
it("preserves hash unchanged", () => {
const snapshot = makeSnapshot({ gateway: { auth: { token: "secret-token-value-here" } } });
const result = redactConfigSnapshot(snapshot);

View File

@@ -12,7 +12,7 @@ export const REDACTED_SENTINEL = "__OPENCLAW_REDACTED__";
* Patterns that identify sensitive config field names.
* Aligned with the UI-hint logic in schema.ts.
*/
const SENSITIVE_KEY_PATTERNS = [/token/i, /password/i, /secret/i, /api.?key/i];
const SENSITIVE_KEY_PATTERNS = [/token$/i, /password/i, /secret/i, /api.?key/i];
function isSensitiveKey(key: string): boolean {
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(key));

View File

@@ -731,7 +731,7 @@ export const FIELD_PLACEHOLDERS: Record<string, string> = {
"agents.list[].identity.avatar": "avatars/openclaw.png",
};
export const SENSITIVE_PATTERNS = [/token/i, /password/i, /secret/i, /api.?key/i];
export const SENSITIVE_PATTERNS = [/token$/i, /password/i, /secret/i, /api.?key/i];
export function isSensitivePath(path: string): boolean {
return SENSITIVE_PATTERNS.some((pattern) => pattern.test(path));

View File

@@ -745,7 +745,7 @@ const FIELD_PLACEHOLDERS: Record<string, string> = {
"agents.list[].identity.avatar": "avatars/openclaw.png",
};
const SENSITIVE_PATTERNS = [/token/i, /password/i, /secret/i, /api.?key/i];
const SENSITIVE_PATTERNS = [/token$/i, /password/i, /secret/i, /api.?key/i];
function isSensitiveConfigPath(path: string): boolean {
return SENSITIVE_PATTERNS.some((pattern) => pattern.test(path));