Skip to content

fix(media): keep script-capable sources out of links and frames - #148

Open
pratikbuilds wants to merge 2 commits into
corbitsdev:mainfrom
pratikbuilds:claude/i142-media-viewer-af93aa
Open

pratikbuilds wants to merge 2 commits into
corbitsdev:mainfrom
pratikbuilds:claude/i142-media-viewer-af93aa

Conversation

@pratikbuilds

Copy link
Copy Markdown
Collaborator

Summary

Keeps script-capable sources out of links and frames in MediaViewer, and closes a viewer whose item left the list (findings 2, 3 and 4).

  • 2, Download link: the link reused the media-element allowlist, which lets data:image/svg+xml through. That is safe in an <img>, but as a target="_blank" href it opens an SVG document that can run script. The link now uses a "link" sink (the internal "frame" sink, renamed) that accepts only http:, https: and blob:. A data: image still shows; it just gets no Download link.
  • 3, PDF preview removed: PDFs rendered in an unsandboxed <iframe>, so a URL labelled as a PDF that serves HTML ran script. Chrome refuses its PDF viewer in any sandboxed frame, and checking the bytes would mean fetching the URL, so a PDF now shows "No preview for this file." with its Download link. In Chrome, Download opens the native PDF viewer in a new tab.
  • 4, shrinking lists: when the open item fell off a shortened list, the index read as closed but stayed stored, so the viewer reopened when the list grew back. An effect keyed on going out of range now commits the close: uncontrolled state clears, and a controlled caller gets one onIndexChange(null).

Behaviour change: PDFs no longer preview inline. The README row and the component docs say so.

Verification

  • bun run check
  • Updated tests in media-src.test.ts, media-viewer.test.tsx and use-media-viewer.test.ts

Closes #142

Addresses findings 2, 3 and 4 of corbitsdev#142.

2. The Download link reused the media-element allowlist, which lets a
   data:image/svg+xml through: safe in an <img>, but as a target="_blank"
   href it opens an SVG document that can run script. The link now uses
   a "link" sink (the old "frame" sink, renamed now that no frame uses
   it) that takes only http:, https: and blob:. A data: image still
   shows; it is just not offered for download.

3. PDFs rendered in an unsandboxed <iframe>, so a URL labelled as a PDF
   that serves HTML ran script, same-origin for blob: and same-origin
   http(s), and could navigate the top page. A short spike, run in
   Playwright's new-headless Chromium and in installed Chrome stable,
   showed Chrome refuses its PDF viewer in any sandboxed frame. It shows
   the "blocked" page for sandbox="", "allow-scripts", "allow-same-origin"
   and even "allow-scripts allow-same-origin", which would also void the
   sandbox for a same-origin URL. <object>/<embed> were not tried: per
   the HTML spec they follow the response's Content-Type, so they would
   not refuse HTML either. Proving the bytes are
   a PDF would mean fetching the URL, which needs CORS and goes against
   the package's no-fetching rule. So a PDF now gets the "No preview for
   this file." state with its Download link, which in Chrome opens the
   native viewer in a new tab.

4. When the open item fell off a shortened list, the index read as
   closed but stayed stored, so the viewer reopened when the list grew
   back. An effect keyed on falling out of range now commits the close:
   uncontrolled state clears, and a controlled caller gets one
   onIndexChange(null) even if it keeps passing the stale index.
@corbits-triage

corbits-triage Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Triage: Fail

@pratikbuilds, please address the following:

  • mixes unrelated changes, not part of fix(media): keep script-capable sources out of links and frames

Triage will request changes.

@corbits-triage corbits-triage Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Triage requests changes:

  • Focused: mixes unrelated changes

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

All contributors have signed the CLA.
Posted by the CLA Assistant Lite bot.

@corbits-triage corbits-triage Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Triage requests changes:

  • CI green: required checks are failing
  • No ai attribution: a commit message contains "Co-Authored-By:"; remove it

@cursor
cursor Bot force-pushed the claude/i142-media-viewer-af93aa branch from e46130d to ddce89f Compare October 30, 2026 12:10
This pull request now only keeps script-capable sources out of links and frames.

@corbits-triage corbits-triage Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Triage requests changes:

  • Focused: mixes unrelated changes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow-ups from the conversation PR review

1 participant