fix: restore redacted SecretRef id during config.set round-trip#54848
fix: restore redacted SecretRef id during config.set round-trip#54848CoCoManYY wants to merge 2 commits into
Conversation
`redactSecretRefId` preserves the SecretRef object structure and only redacts the `id` field, but `restoreRedactedValues` has no corresponding logic to detect and restore it. When a config obtained from `config.get` is passed back to `config.set`, the redacted `id` (__OPENCLAW_REDACTED__) fails JSON Pointer validation with: "File secret reference id must be an absolute JSON pointer" Add `restoreSecretRefId` (symmetric to `redactSecretRefId`) and call it in both `restoreRedactedValuesWithLookup` and `restoreRedactedValuesGuessing` before recursing into objects, so that SecretRef objects survive a Web UI / API round-trip unmodified.
Greptile SummaryThis PR fixes a symmetric redaction/restore bug for Confidence Score: 5/5This PR is safe to merge — the fix is minimal, surgical, and correctly symmetric to the existing redaction logic. The new restoreSecretRefId function mirrors redactSecretRefId exactly: it only replaces id when it equals the sentinel, and leaves everything else untouched. All three restore code paths are updated consistently. Edge cases (non-redacted id, missing/null original, original not a SecretRef) all fall through to the pre-existing logic unchanged. No files require special attention. Reviews (1): Last reviewed commit: "fix: restore redacted SecretRef id durin..." | Re-trigger Greptile |
|
Thanks @CoCoManYY for the contribution on SecretRef id restoration. This is now fully covered by #58044 (merged), which landed the round-trip restore fix in the broader hardened implementation and test set. Closing this PR as superseded by #58044. |
Summary
Fix asymmetric redaction/restore for SecretRef objects in
config.set.redactSecretRefIdpreserves the SecretRef structure and only redacts theidfield, butrestoreRedactedValueshas no corresponding logic to restore it.config.setto fail with"File secret reference id must be an absolute JSON pointer"when the config contains file-based SecretRef objects (e.g.models.providers.*.headers.*orgateway.auth.token).Changes
restoreSecretRefIdinredact-snapshot.secret-ref.ts(symmetric toredactSecretRefId)idin bothrestoreRedactedValuesWithLookupandrestoreRedactedValuesGuessingbefore recursing into objectsReproduction
config.get→ returns{ source: "file", provider: "my-secret-provider", id: "__OPENCLAW_REDACTED__" }config.set→ fails validation:Root Cause
During redaction,
redactSecretRefIddoes SecretRef-aware redaction — only replacesid, preservingsourceandprovider. But during restoration, the code recurses into the object and encountersid: "__OPENCLAW_REDACTED__"at a path likemodels.providers.*.headers.x-api-key.id, which doesn't matchisSensitivePath()patterns, so the sentinel value is left as-is and fails schema validation.Test plan
config.get→config.setround-trip with file SecretRef no longer fails validationid(e.g. env var placeholder) passes through unchanged🤖 AI-assisted PR — code reviewed and tested manually.