fix(gateway): redact secrets in skills.update response#69998
Conversation
Greptile SummaryThis PR fixes a credential-leak bug in Confidence Score: 5/5Safe to merge — the redaction logic is correct and the only finding is a minor test assertion style issue. The production change is a single, well-understood call to an already-proven utility. All remaining feedback is P2 (weak test assertion style) and does not block merge. No files require special attention. Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/gateway/server-methods/skills.update.normalizes-api-key.test.ts
Line: 91-95
Comment:
**Weak redaction assertions allow false positives**
The `.not.toBe()` checks pass for any value other than the plaintext secret — including `undefined`, `null`, or an empty string — so a bug that silently drops the `apiKey` key or replaces it with `null` would not be caught. Asserting the exact sentinel value would make these tests meaningfully verify the redaction contract.
```suggestion
expect(config.apiKey).toBe("__OPENCLAW_REDACTED__");
const env = config.env as Record<string, string>;
expect(env.GEMINI_API_KEY).toBe("__OPENCLAW_REDACTED__");
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "chore(changelog): add entry for skills.u..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 986fb542d7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
cc @hxy91819 . |
|
Related work from PRtags group Title: Open PR duplicate: [Bug]: skills.update echoes raw apiKey and env secrets in gateway response
|
steipete
left a comment
There was a problem hiding this comment.
This is the right canonical fix for #66769: using redactConfigObject(current) is better than local hand-rolled masking because it covers nested config, SecretRef-shaped values, and sensitive-path heuristics consistently with the rest of config reads.
One repo-policy blocker before merge: this dropped the changelog entry in the last commit. Please add a single-line CHANGELOG.md entry under the active ### Fixes section with attribution, e.g. Thanks @Ziy1-Tan, and keep the exact sentinel assertions you added in the test.
986fb54 to
485f53f
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 485f53f4ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
3565d61 to
14992e8
Compare
|
Codex automated review: keeping this open. Keep this PR open. Current main still returns the updated Best possible solution: Keep this PR open. The best path is to finish review on the current head, resolve or explain the failing checks, then land the focused gateway change plus regression tests so it closes #66769. The latest PR head is a better candidate than closing/reopening duplicate attempts because it fixes the main leak and preserves existing secrets when clients round-trip redacted sentinel values. What I checked:
Remaining risk / open question:
Codex Review notes: model gpt-5.5, reasoning high; reviewed against a35ad200d1d1. |
14992e8 to
94d979d
Compare
94d979d to
12d7073
Compare
12d7073 to
b75062a
Compare
skills.update was returning the full updated SkillConfig entry including plaintext apiKey and env values in the RPC response. This could leak credentials into Control UI WebSocket traffic, client logs, or session transcripts. Fix by passing the response config through the existing redactConfigObject() utility, which already handles all sensitive paths (apiKey, tokens, passwords, secret-named env keys, etc.) via isSensitiveConfigPath(). Config is still written to disk in full — only the response payload is redacted. Fixes openclaw#66769
Use __OPENCLAW_REDACTED__ sentinel value instead of .not.toBe() to properly verify the redaction contract — weak negation checks would pass even if the field were silently dropped or set to null.
Co-authored-by: Copilot <[email protected]>
98b1b04 to
8dae600
Compare
Co-authored-by: Copilot <[email protected]>
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Merged via squash.
Thanks @Ziy1-Tan! |
Merged via squash. Prepared head SHA: 61fc06f Co-authored-by: Ziy1-Tan <[email protected]> Co-authored-by: hxy91819 <[email protected]> Reviewed-by: @hxy91819
Merged via squash. Prepared head SHA: 61fc06f Co-authored-by: Ziy1-Tan <[email protected]> Co-authored-by: hxy91819 <[email protected]> Reviewed-by: @hxy91819
Merged via squash. Prepared head SHA: 61fc06f Co-authored-by: Ziy1-Tan <[email protected]> Co-authored-by: hxy91819 <[email protected]> Reviewed-by: @hxy91819
Merged via squash. Prepared head SHA: 61fc06f Co-authored-by: Ziy1-Tan <[email protected]> Co-authored-by: hxy91819 <[email protected]> Reviewed-by: @hxy91819
Merged via squash. Prepared head SHA: 61fc06f Co-authored-by: Ziy1-Tan <[email protected]> Co-authored-by: hxy91819 <[email protected]> Reviewed-by: @hxy91819
Merged via squash. Prepared head SHA: 61fc06f Co-authored-by: Ziy1-Tan <[email protected]> Co-authored-by: hxy91819 <[email protected]> Reviewed-by: @hxy91819
Summary
skills.updatewas returning the full updatedSkillConfigentry — including plaintextapiKeyandenvvalues — in the RPC response. This could leak credentials into:Fix
Pass the response config through the existing
redactConfigObject()utility before returning it. This reuses the same redaction infrastructure used byconfig.get, which already handles all sensitive paths viaisSensitiveConfigPath()(apiKey,token,password,secret, etc.).Config is still written to disk in full — only the RPC response payload is redacted.
Diff surface: +2 lines in production code (1 import, 1 call site).
Testing
strips embedded CR/LF from apiKey— still passes, config written correctlyredacts apiKey and secret env values from the response but writes full values to configapiKeyis redacted in responseenvkey (GEMINI_API_KEY) is redacted in responseenvkey (BRAVE_REGION) is still returnedAI Transparency
Fixes #66769