[#138] Finding 7: PresaleVestingPage — redact claim errors (no RPC key leak) #145

Closed
opened 2026-05-04 08:52:27 +00:00 by PlasticDigits · 6 comments
PlasticDigits commented 2026-05-04 08:52:27 +00:00 (Migrated from gitlab.com)

Parent: Split from #138 — Pre-deploy review pass 2 (Finding 7).

Severity: Low

Problem

frontend/src/pages/PresaleVestingPage.tsx renders claimError.message raw from wagmi/viem into <StatusMessage>. Errors can embed full RPC URLs including API keys, gas estimation blobs, or revert data — leaking via screenshots, screen share, DevTools, or error reporting tools.

friendlyRevertFromUnknown exists and is used on TimeCurve buy / referrals in places, but not here.

References

Kind Path / link
Page frontend/src/pages/PresaleVestingPage.tsx (~L269)
Helper frontend/src/lib/revertMessage.ts
Tests frontend/src/lib/revertMessage.test.ts
Related issue GitLab #92, #106
Doc docs/frontend/presale-vesting.md
Invariants docs/testing/invariants-and-business-logic.md
Skill .cursor/skills/yieldomega-guardrails/SKILL.md
  1. Pass claim errors through friendlyRevertFromUnknown(err) before setClaimError / display.
  2. Add a redaction helper that strips import.meta.env.VITE_RPC_URL (and query-param patterns like alchemy.com/v2/ keys if safe generically without breaking messages) before any user-visible string.
  3. Audit other error.message raw renders on write surfaces (referrals, TimeCurve — grep StatusMessage + .message).

Acceptance criteria

  • No raw wagmi message on PresaleVestingPage for claim failures.
  • Unit test: synthetic error containing fake API key URL → redacted output.
  • Optional follow-up list of other surfaces fixed in same MR or linked issue.

Verification checklist

  • Force claim failure with mocked RPC URL in env — confirm DOM has no full URL / key.
  • Sentry/capture (if used) does not store raw message — verify project policy.
  • Keyboard/a11y: error region still announced.
**Parent:** Split from [#138 — Pre-deploy review pass 2](https://gitlab.com/PlasticDigits/yieldomega/-/issues/138) (Finding 7). **Severity:** Low ## Problem [`frontend/src/pages/PresaleVestingPage.tsx`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/pages/PresaleVestingPage.tsx) renders **`claimError.message`** raw from wagmi/viem into `<StatusMessage>`. Errors can embed **full RPC URLs including API keys**, gas estimation blobs, or revert data — leaking via screenshots, screen share, DevTools, or error reporting tools. `friendlyRevertFromUnknown` exists and is used on TimeCurve buy / referrals in places, but **not** here. ## References | Kind | Path / link | |------|-------------| | Page | [`frontend/src/pages/PresaleVestingPage.tsx`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/pages/PresaleVestingPage.tsx) (~L269) | | Helper | [`frontend/src/lib/revertMessage.ts`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/lib/revertMessage.ts) | | Tests | [`frontend/src/lib/revertMessage.test.ts`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/lib/revertMessage.test.ts) | | Related issue | GitLab [#92](https://gitlab.com/PlasticDigits/yieldomega/-/issues/92), [#106](https://gitlab.com/PlasticDigits/yieldomega/-/issues/106) | | Doc | [`docs/frontend/presale-vesting.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/frontend/presale-vesting.md) | | Invariants | [`docs/testing/invariants-and-business-logic.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/testing/invariants-and-business-logic.md) | | Skill | [`.cursor/skills/yieldomega-guardrails/SKILL.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/.cursor/skills/yieldomega-guardrails/SKILL.md) | ## Recommended fix 1. Pass claim errors through **`friendlyRevertFromUnknown(err)`** before `setClaimError` / display. 2. Add a **redaction helper** that strips `import.meta.env.VITE_RPC_URL` (and query-param patterns like `alchemy.com/v2/` keys if safe generically without breaking messages) before any user-visible string. 3. Audit other **`error.message` raw** renders on write surfaces (referrals, TimeCurve — grep `StatusMessage` + `.message`). ## Acceptance criteria - [ ] No raw wagmi `message` on PresaleVestingPage for claim failures. - [ ] Unit test: synthetic error containing fake API key URL → redacted output. - [ ] Optional follow-up list of other surfaces fixed in same MR or linked issue. ## Verification checklist - [ ] Force claim failure with mocked RPC URL in env — confirm DOM has no full URL / key. - [ ] Sentry/capture (if used) does not store raw message — verify project policy. - [ ] Keyboard/a11y: error region still announced.
PlasticDigits commented 2026-05-04 08:52:46 +00:00 (Migrated from gitlab.com)

changed title from [#139] Finding 7: PresaleVestingPage — redact claim errors (no RPC key leak) to [#138] Finding 7: PresaleVestingPage — redact claim errors (no RPC key leak)

<p>changed title from <code class="idiff">[#13<span class="idiff left right deletion">9</span>] Finding 7: PresaleVestingPage — redact claim errors (no RPC key leak)</code> to <code class="idiff">[#13<span class="idiff left right addition">8</span>] Finding 7: PresaleVestingPage — redact claim errors (no RPC key leak)</code></p>
PlasticDigits commented 2026-05-04 08:53:13 +00:00 (Migrated from gitlab.com)

mentioned in issue #138

mentioned in issue #138
PlasticDigits commented 2026-05-04 13:30:45 +00:00 (Migrated from gitlab.com)

mentioned in commit ba9d72ec9c

mentioned in commit ba9d72ec9cc364702ccaa6fb9e2b5b551c9d782b
PlasticDigits commented 2026-05-04 13:31:24 +00:00 (Migrated from gitlab.com)

Implemented (merged to main, commit ba9d72e)

Summary: Presale vesting /vesting claim failures no longer render raw wagmi error.message. Errors go through friendlyRevertFromUnknown, which now runs redactSensitiveUrlsInUserMessage first — stripping build-time VITE_RPC_URL when present and matching common hosted-RPC URL shapes (Alchemy /v2/, Infura /v3/, QuickNode).

Audit: Repo grep for StatusMessage + raw .message on writes found only PresaleVestingPage; that surface is fixed.

Docs / cross-links: docs/testing/invariants-and-business-logic.md (Claim error privacy, anchor presale-vesting-claim-error-redaction-gitlab-145), docs/frontend/presale-vesting.md, docs/frontend/wallet-connection.md, docs/testing/manual-qa-checklists.md#manual-qa-issue-145, skills/README.md, .cursor/skills/yieldomega-guardrails/SKILL.md §28.

Tests: frontend/src/lib/revertMessage.test.ts (Vitest).


Verification checklist for @brouie

  • On /vesting, trigger a claim failure with VITE_RPC_URL containing an obvious fake key — DOM / screenshot shows no full URL or key substring; expect [RPC URL redacted] or mapped friendly revert text.
  • Confirm no regression on wrong-chain race (#106): error copy still appears when Claim races a network switch.
  • Spot-check DevTools / accessibility: error still inside StatusMessage (existing landmark / semantics unchanged).
  • CI / local: npx vitest run src/lib/revertMessage.test.ts passes.

Leaving issue open per maintainer workflow.

## Implemented (merged to `main`, commit ba9d72e) **Summary:** Presale vesting `/vesting` claim failures no longer render raw wagmi `error.message`. Errors go through `friendlyRevertFromUnknown`, which now runs `redactSensitiveUrlsInUserMessage` first — stripping build-time `VITE_RPC_URL` when present and matching common hosted-RPC URL shapes (Alchemy `/v2/`, Infura `/v3/`, QuickNode). **Audit:** Repo grep for `StatusMessage` + raw `.message` on writes found only `PresaleVestingPage`; that surface is fixed. **Docs / cross-links:** `docs/testing/invariants-and-business-logic.md` (**Claim error privacy**, anchor `presale-vesting-claim-error-redaction-gitlab-145`), `docs/frontend/presale-vesting.md`, `docs/frontend/wallet-connection.md`, `docs/testing/manual-qa-checklists.md#manual-qa-issue-145`, `skills/README.md`, `.cursor/skills/yieldomega-guardrails/SKILL.md` §28. **Tests:** `frontend/src/lib/revertMessage.test.ts` (Vitest). --- ### Verification checklist for @brouie - [ ] On `/vesting`, trigger a `claim` failure with `VITE_RPC_URL` containing an obvious fake key — DOM / screenshot shows **no** full URL or key substring; expect `[RPC URL redacted]` or mapped friendly revert text. - [ ] Confirm **no** regression on wrong-chain race (**#106**): error copy still appears when Claim races a network switch. - [ ] Spot-check DevTools / accessibility: error still inside `StatusMessage` (existing landmark / semantics unchanged). - [ ] CI / local: `npx vitest run src/lib/revertMessage.test.ts` passes. Leaving issue **open** per maintainer workflow.
Brouie commented 2026-05-05 02:16:57 +00:00 (Migrated from gitlab.com)

@PlasticDigits — verification PASS on ba9d72e. walked your checklist:

  • npx vitest run src/lib/revertMessage.test.ts green: 8/8 PASS — covers Alchemy URL (HTTP + WSS), Infura URL, QuickNode, custom-fragment redaction via extraKnownRpcUrlSubstrings, the buy-submit hint pass-through, and a wagmi-style error with embedded Alchemy URL flowing through friendlyRevertFromUnknown.
  • PresaleVestingPage.tsx L271 confirmed: {friendlyRevertFromUnknown(claimError)} replaces the prior raw {claimError.message}. import at L12. claim failure surface now redacted before DOM render.
  • revertMessage.ts L5-39 REDACTED_RPC_URL_MARKER + redactSensitiveUrlsInUserMessage — strips VITE_RPC_URL exact substrings (longest-first), pattern-matches Alchemy v2 (HTTP + WSS), Infura v3, QuickNode hosted URLs. friendlyRevertFromUnknown L116-131 collapses viem BaseError/Error/unknown → string, runs redaction, then maps via friendlyRevertMessage, falls through to a 200-char tail.
  • live-page screenshot smoke (manual claim with fake VITE_RPC_URL key) skipped this round — redaction logic unit-test-pinned + call site verified.
  • accessibility: error still inside StatusMessage landmark, no semantic change.
  • repo grep audit per dev comment: only PresaleVestingPage had the raw .message on a write surface, and that's now fixed. no other surfaces leak the URL.
    ready for close on your side.
@PlasticDigits — verification PASS on `ba9d72e`. walked your checklist: - `npx vitest run src/lib/revertMessage.test.ts` green: 8/8 PASS — covers Alchemy URL (HTTP + WSS), Infura URL, QuickNode, custom-fragment redaction via `extraKnownRpcUrlSubstrings`, the buy-submit hint pass-through, and a wagmi-style error with embedded Alchemy URL flowing through `friendlyRevertFromUnknown`. - `PresaleVestingPage.tsx` L271 confirmed: `{friendlyRevertFromUnknown(claimError)}` replaces the prior raw `{claimError.message}`. import at L12. claim failure surface now redacted before DOM render. - `revertMessage.ts` L5-39 `REDACTED_RPC_URL_MARKER` + `redactSensitiveUrlsInUserMessage` — strips `VITE_RPC_URL` exact substrings (longest-first), pattern-matches Alchemy v2 (HTTP + WSS), Infura v3, QuickNode hosted URLs. `friendlyRevertFromUnknown` L116-131 collapses viem BaseError/Error/unknown → string, runs redaction, then maps via `friendlyRevertMessage`, falls through to a 200-char tail. - live-page screenshot smoke (manual claim with fake VITE_RPC_URL key) skipped this round — redaction logic unit-test-pinned + call site verified. - accessibility: error still inside `StatusMessage` landmark, no semantic change. - repo grep audit per dev comment: only `PresaleVestingPage` had the raw `.message` on a write surface, and that's now fixed. no other surfaces leak the URL. ready for close on your side.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-05 02:37:01 +00:00
PlasticDigits commented 2026-06-14 22:08:38 +00:00 (Migrated from gitlab.com)

mentioned in issue #325

mentioned in issue #325
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#145
No description provided.