Skip to content

fix(#266): validate share-link spec.view before writing resultView#273

Merged
BorisTyshkevich merged 1 commit into
mainfrom
fix/sharelink-view-guard-266
Jul 17, 2026
Merged

fix(#266): validate share-link spec.view before writing resultView#273
BorisTyshkevich merged 1 commit into
mainfrom
fix/sharelink-view-guard-266

Conversation

@BorisTyshkevich

Copy link
Copy Markdown
Collaborator

What & why

Closes #266.

src/main.ts (share-link bootstrap) wrote queryView(spec) — the share's
spec.view — into app.state.resultView with only a legacy chartpanel
remap and no validation against the view enum. The v2 tagged decode
(core/share.jswithQuerySpec) passes spec.view through verbatim, so a
crafted share link could set resultView to an arbitrary string. state.ts
pins the signal type at compile time only; the .js-era glue left the runtime
ingress unguarded.

Fix: narrow the launch view against SAVED_VIEWS before assigning, mirroring
the Library-activation guard in ui/saved-history.ts:

  • a Filter-role preview still wins (rolePreview),
  • a persisted table/json/panel restores,
  • legacy view: "chart" still maps to panel (load-bearing — the v2 decode
    path skips upgradeSavedQuery, unlike Library rows),
  • any other value silently falls back to the default view (the decision the
    issue deferred: fall back, consistent with the sibling path, no new diagnostic
    surface).

Adds a unit test for the crafted-view case (view: "javascript:alert(1)"
stays table). main.ts remains at 100% coverage; all 2867 tests pass.

Checklist

  • npm test passes (the per-file coverage gate is non-negotiable)
  • Tests added/updated in the same change as the code
  • npm run build succeeds (single-file dist/sql.html)
  • Layers kept honest: pure logic in src/core/, network in src/net/ (injected fetch), DOM in src/ui/
  • No new runtime dependency (or it's a deliberate, justified addition — see CONTRIBUTING)
  • README / CHANGELOG.md ([Unreleased]) updated if behavior or the deployed surface changed
  • Reconciled affected tracked work (roadmap Roadmap to 1.0.0 #68, the issue body, ADR/CHANGELOG) if this change reshaped it

🤖 Generated with Claude Code

The share-link bootstrap wrote `queryView(spec)` (and a role preview) into
`app.state.resultView` with only a legacy `chart`→`panel` remap and no
enum check. The v2 tagged decode (`core/share.js`) passes `spec.view`
through verbatim, so a crafted share link could set `resultView` to an
arbitrary string.

Narrow the value against `SAVED_VIEWS` (mirroring the Library-activation
guard in `ui/saved-history.ts`): a Filter-role preview still wins, a
persisted table/json/panel restores, legacy `chart` still maps to `panel`,
and any other value silently falls back to the default view. Adds a unit
test for the crafted-view case; main.ts stays at 100% coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XP1KN94N969SVMNFPdVtGg
@BorisTyshkevich
BorisTyshkevich merged commit 917548c into main Jul 17, 2026
7 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.

Share-link bootstrap writes unvalidated spec.view into resultView

1 participant