#12792: fix: exclude 'tokens' (plural) fields from config redaction
stale
Cluster:
Config Redaction Improvements
#### Summary
The config redaction logic uses `/token/i` as a sensitive key pattern, which matches `maxTokens` (because it contains "token"). This causes the numeric `maxTokens` value to be replaced with the string `"__OPENCLAW_REDACTED__"`, breaking schema validation when saving config through the Control UI.
Fixes #12078.
lobster-biscuit
#### Repro Steps
1. Configure a local provider (e.g. LM Studio) with a model entry that includes `maxTokens: 10000`
2. Open Control UI → Config
3. Change any unrelated setting (e.g. `update.checkOnStart: true`)
4. Hit Save → fails with "Invalid Config" because `maxTokens` is now the string `"__OPENCLAW_REDACTED__"` instead of a number
#### Root Cause
`SENSITIVE_KEY_PATTERNS` in `src/config/redact-snapshot.ts` includes `/token/i`, which matches any key containing "token" — including `maxTokens`, `inputTokens`, `outputTokens`, `contextTokens`, etc. These are numeric config fields, not secrets.
The pattern: sensitive keys always use **"token" (singular)** (`token`, `botToken`, `appToken`, `webhookToken`), while non-sensitive keys use **"tokens" (plural)** (`maxTokens`, `inputTokens`, `outputTokens`).
#### Behavior Changes
- Changed `/token/i` to `/token(?!s)/i` — matches "token" not followed by "s"
- `token`, `botToken`, `appToken`, `webhookToken` → still redacted (singular)
- `maxTokens`, `inputTokens`, `outputTokens` → no longer redacted (plural)
- No other patterns changed; `password`, `secret`, `apiKey` unaffected
#### Codebase and GitHub Search
- Searched for all uses of `SENSITIVE_KEY_PATTERNS` and `isSensitiveKey` — only used in `redact-snapshot.ts`
- Searched config schema for fields matching `/token/i` to verify singular = secret, plural = not
- Verified `restoreRedactedValues` round-trip still works (existing test)
#### Tests
All 25 tests pass (`pnpm check` + `pnpm test`):
- **New: "does not redact 'tokens' (plural) fields like maxTokens (#12078)"** — verifies `maxTokens` stays `10000` while `apiKey` is still redacted
- All 17 existing `redactConfigSnapshot` tests pass, including:
- `token`, `botToken`, `appToken`, `webhookToken/Secret` fields still redacted
- Numeric `token: 1234` still redacted (singular "token")
- All 7 existing `restoreRedactedValues` tests pass, including round-trip test
**Sign-Off**
- Models used: Claude claude-4.6-opus-high-thinking (Cursor agent)
- Submitter effort: guided/reviewed by human
Made with [Cursor](https://cursor.com)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR narrows the gateway-side config redaction key matcher from `/token/i` to `/token(?!s)/i` so numeric config fields like `maxTokens`/`inputTokens`/`outputTokens` are no longer replaced with the redaction sentinel. It also adds a regression test asserting `maxTokens` is preserved while true secrets like `apiKey` remain redacted.
The change is localized to `src/config/redact-snapshot.ts`, which deep-walks config snapshots and also scrubs the raw JSON5 text using the same `isSensitiveKey` logic. This directly addresses the Control UI “Invalid Config” failure caused by redacting numeric `*Tokens` fields.
<h3>Confidence Score: 4/5</h3>
- Generally safe to merge, but there is a UI/schema sensitivity mismatch to fix for consistent behavior.
- The functional fix is small and covered by a targeted test. However, the PR description claims alignment with UI-hint logic, but `src/config/schema.ts` still uses `/token/i`, which will continue to treat plural `*Tokens` paths as sensitive in the UI even though they are no longer redacted server-side.
- src/config/schema.ts (sensitive-path matcher), src/config/redact-snapshot.ts (pattern change)
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#11208: fix(config): prevent __OPENCLAW_REDACTED__ corruption on config writes
by janckerchen · 2026-02-07
83.5%
#23654: security(cli): redact sensitive values in config get output
by SleuthCo · 2026-02-22
82.9%
#16708: fix(security): OC-17 add token redaction to error formatting, depre...
by aether-ai-agent · 2026-02-15
78.8%
#15756: [Security]: strip provider apiKey from models.json before prompt se...
by SecBear · 2026-02-13
77.4%
#19115: fix(logging): improved redaction for config objects and unquoted keys
by Clawborn · 2026-02-17
77.0%
#12296: security: persistence-only secret redaction for session transcripts
by akoscz · 2026-02-09
76.2%
#21901: fix: guard writeConfigFile against persisting redaction sentinels
by Protocol-zero-0 · 2026-02-20
76.0%
#10943: fix(config): resolve Control UI "Unsupported schema node" for confi...
by kraftbj · 2026-02-07
75.6%
#10807: fix(config): coerce numeric meta.lastTouchedAt to ISO string
by mcaxtr · 2026-02-07
75.1%
#11141: Fix JSON schema conversion error when using llama.cpp backend
by 9nix00 · 2026-02-07
74.8%