Skip to content

fix: redact received payload values from response validation errors#121

Merged
andrewkoltsov merged 2 commits into
masterfrom
claude/lib-7-narrow-error-path-test-gaps
Jun 6, 2026
Merged

fix: redact received payload values from response validation errors#121
andrewkoltsov merged 2 commits into
masterfrom
claude/lib-7-narrow-error-path-test-gaps

Conversation

@andrewkoltsov

Copy link
Copy Markdown
Owner

Summary

summarizeIssues in src/sdk/validation/responseValidation.ts built error strings straight from Valibot's default issue messages, which embed the raw received value — e.g. password: Invalid type: Expected number but received "hunter2-SECRET". Since validated payloads can carry secrets (passwords, tokens, child PII) that the Librus server echoes back, LibrusResponseValidationError.details.issues could leak them.

Flagged as a "mild secret-adjacent risk" in .tasks/rearchitect/08-test-coverage.md and confirmed empirically while working LIB-7. Kept out of LIB-7 because that task was tests-only / no production changes.

Change

  • Added redactReceivedValue, which rebuilds each issue summary from the Invalid <label>: prefix and issue.expected only — both schema-derived — and never includes issue.received. Chosen over regex-stripping the received … suffix because it can't miss the no-expected message form (Invalid type: Received null). No schema under src/sdk/validation/ sets a custom message:, so all messages follow Valibot's default Invalid <label>: shape.
  • Added a guard test parsing { password: "hunter2-SECRET", token: "Bearer-LEAK" } against v.object({ password: v.number(), token: v.number() }) and asserting no issue summary contains either secret.

Verification

  • vitest run test/responseValidation.truncation.test.ts — 7/7 pass (6 existing + 1 new).
  • tsc --noEmit and eslint clean. Existing format/truncation tests unaffected.

🤖 Generated with Claude Code

andrewkoltsov and others added 2 commits June 6, 2026 20:52
Closes the unmet LIB-7 acceptance criterion requiring a fast-check
property test for abort-signal composition. Verifies that for any
ordering of timeout/upstream aborts, the combined signal aborts exactly
once with the first reason. Runs in ~130ms (200 runs), well under 1s.

No production code changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Valibot's default issue messages embed the raw received value (e.g.
`Expected number but received "hunter2-SECRET"`). Since validated payloads
can carry secrets (passwords, tokens, child PII) that Librus echoes back,
`LibrusResponseValidationError.details.issues` could leak them.

Rebuild each issue summary from the `Invalid <label>:` prefix and
`issue.expected` only, never `issue.received`. Add a guard test asserting
no summary contains the crafted secret substrings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@andrewkoltsov andrewkoltsov merged commit f69ca73 into master Jun 6, 2026
11 checks passed
@andrewkoltsov andrewkoltsov deleted the claude/lib-7-narrow-error-path-test-gaps branch June 6, 2026 20:20
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