fix(tradein-frontend): safeUrl validator, apiFetch dedup, ListingsCard a11y, error boundary #512

Merged
lekss361 merged 1 commit from feat/tradein-frontend-security-a11y into main 2026-05-24 11:47:39 +00:00

1 commit

Author SHA1 Message Date
lekss361
5bd9c2f66d fix(tradein-frontend): safeUrl validator, apiFetch dedup, ListingsCard a11y, error boundary
Four security/UX fixes from 2026-05-24 audit:

* lib/safeUrl.ts (new): validate external URLs, reject non-http(s) schemes
  (closes finding #3 — backend supplies lot.source_url verbatim from scraped
  sites; javascript:/data:/file: would have executed on click).
* lib/api.ts: refactor apiFetch to delegate to apiFetchWithStatus — single
  read-body-once implementation, drops the body-stream-twice anti-pattern
  (finding #8).
* components/trade-in/ListingsCard.tsx: drop tr.onClick (not keyboard
  accessible), keep the inline <a> as the only interactive element, gate it
  through safeUrl() (findings #7 + #3).
* app/error.tsx (new): Next 15 App Router route-segment error boundary —
  prevents white-screen on component crash (finding #16).

Scope-cut from original audit:
* #17 (sessionId crypto.randomUUID) — already implemented in sessionId.ts;
  no change needed.
* safeUrl wiring in DealsCard / IMVBenchmark — neither renders user-supplied
  URLs (DealsCard has no links, IMVBenchmark links a hardcoded domain).
2026-05-24 14:38:56 +03:00