Skip to content

fix: redact secrets in machine-readable error envelopes - #29

Merged
subalee merged 1 commit into
mainfrom
feature/upt-3572-cli-error-envelopes-bypass-secret-redaction-details
Aug 12, 2026
Merged

fix: redact secrets in machine-readable error envelopes#29
subalee merged 1 commit into
mainfrom
feature/upt-3572-cli-error-envelopes-bypass-secret-redaction-details

Conversation

@subalee

@subalee subalee commented Aug 11, 2026

Copy link
Copy Markdown
Member

Closes UPT-3572.

The gap

redactSecrets ran 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, and message.

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:31 and bin/run.js:60, funnel through it — so it covers the API's details passthrough, the CLI's own bulk failures, and any error shape added later.

This changes no output today

Verified on both live producers:

  • API path — nothing in the published v3 surface emits details.
  • CLI pathsrc/output/bulk-failure.ts:47 does populate details with the failed bulk entries, which is documented behavior. Those entries are {monitorId, monitorName?, status, error?, code?}, and none of those names end in a suffix isSensitiveFieldName matches, so bulk error output is byte-identical. The existing assertions in test/monitors-bulk.test.ts (lines 75 and 109) pass untouched and act as the regression guard.

What changes is that a future endpoint populating details can'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:

  1. Redaction is key-based, so a credential interpolated into a free-text 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.
  2. --reveal-secrets does not lift redaction on errors, unlike on successful output. errorEnvelope also 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:

{"error":{"code":"HTTP_400","details":{"httpPassword":"supersecret","field":"httpPassword"},"message":"Monitor rejected","status":400}}

Two tests added to test/redact-response.test.ts: one proving an API error's details is redacted, one pinning the --reveal-secrets decision.

  • vitest run — 273 passed, 33 files
  • tsc --noEmit — clean
  • oxlint src test scripts — clean
  • oxfmt --check — clean

Summary by CodeRabbit

  • New Features

    • Machine-readable API and CLI error responses now automatically redact recognizable credential values.
    • Redaction remains enabled when --reveal-secrets is used.
    • Non-credential fields remain available for troubleshooting, while raw responses and free-text messages are unchanged.
  • Documentation

    • Updated documentation and changelog to clarify error redaction behavior.

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.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 496dbc1a-b0d0-4269-8e12-8df158bd86ef

📥 Commits

Reviewing files that changed from the base of the PR and between 36a9121 and faf07d6.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • README.md
  • src/lib/cli-errors.ts
  • test/redact-response.test.ts

Walkthrough

The CLI now redacts recognizable credential fields in structured error envelopes. The behavior covers existing and newly created CLI errors, remains active with --reveal-secrets, and leaves free-text messages unchanged.

Changes

Error envelope redaction

Layer / File(s) Summary
Redact structured CLI errors
src/lib/cli-errors.ts
Error payloads now pass through redactSecrets before the CLI returns error envelopes.
Validate and document redaction
test/redact-response.test.ts, README.md, CHANGELOG.md
Tests cover API error details and --reveal-secrets. Documentation describes field-name matching, raw output behavior, and free-text limitations.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/upt-3572-cli-error-envelopes-bypass-secret-redaction-details
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feature/upt-3572-cli-error-envelopes-bypass-secret-redaction-details

Comment @coderabbitai help to get the list of available commands.

@subalee
subalee marked this pull request as ready for review August 12, 2026 08:48
@subalee
subalee merged commit 41e7c11 into main Aug 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant