fix: redact secrets in machine-readable error envelopes - #29
Merged
subalee merged 1 commit intoAug 12, 2026
Merged
Conversation
redactSecrets ran on dry-run previews and successful responses but not on the failure path, so the documented rule that credential-like fields print as [REDACTED] in every format held only for stdout. Redaction now happens in errorEnvelope, the single point where a failure becomes output, covering the API's details passthrough, the CLI's own bulk failure entries, and any error shape added later. No output changes today: nothing in the published v3 surface populates details, and bulk entries carry only monitorId, monitorName, status, error, and code, none of which match a credential suffix. What changes is that a future endpoint cannot leak through this path without a CLI change. Two limits are deliberate. Redaction is key-based, so a credential interpolated into a free-text message is still shown. And --reveal-secrets does not lift redaction on errors the way it does on successful output, because errorEnvelope also serves failures raised before flags are parsed, and failure output is what gets pasted into bug reports, CI logs, and agent transcripts.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
WalkthroughThe CLI now redacts recognizable credential fields in structured error envelopes. The behavior covers existing and newly created CLI errors, remains active with ChangesError envelope redaction
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
subalee
marked this pull request as ready for review
August 12, 2026 08:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes UPT-3572.
The gap
redactSecretsran in exactly two places — dry-run previews (src/lib/request-preview.ts:10) and successful response output (src/lib/operation-command.ts:343). The failure path had none, so the README's rule that credential-like fields "print as[REDACTED]in every format" was true for stdout and false for stderr. This makes the documented guarantee honest rather than adding a new one.Two fields carried API-controlled content unredacted:
details(src/api/errors.ts:19), a blind passthrough of arbitrary JSON, andmessage.The fix
Redaction moves into
errorEnvelope(src/lib/cli-errors.ts) rather than into each error's source. That's the single point where a failure becomes output — both call sites,base-command.ts:31andbin/run.js:60, funnel through it — so it covers the API'sdetailspassthrough, the CLI's own bulk failures, and any error shape added later.This changes no output today
Verified on both live producers:
details.src/output/bulk-failure.ts:47does populatedetailswith the failed bulk entries, which is documented behavior. Those entries are{monitorId, monitorName?, status, error?, code?}, and none of those names end in a suffixisSensitiveFieldNamematches, so bulk error output is byte-identical. The existing assertions intest/monitors-bulk.test.ts(lines 75 and 109) pass untouched and act as the regression guard.What changes is that a future endpoint populating
detailscan't leak through this path without a CLI change.Two deliberate limits
Both are stated in the code comment, the README, and the CHANGELOG rather than left implicit:
message("password 'hunter2' is rejected") is still shown. Catching that needs pattern matching, which carries false-positive risk. The error path becomes consistent, not safe.--reveal-secretsdoes not lift redaction on errors, unlike on successful output.errorEnvelopealso serves failures raised before flags are parsed, so honoring the flag would mean threading state into a path that can't always have it — and failure output is precisely what gets pasted into bug reports, CI logs, and agent transcripts.Test plan
Written test-first. Before the change, the new test failed with the secret on stderr verbatim:
Two tests added to
test/redact-response.test.ts: one proving an API error'sdetailsis redacted, one pinning the--reveal-secretsdecision.vitest run— 273 passed, 33 filestsc --noEmit— cleanoxlint src test scripts— cleanoxfmt --check— cleanSummary by CodeRabbit
New Features
--reveal-secretsis used.Documentation