mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user