Skip to content

K-Fujimura/gh-html-attachment-preview

Repository files navigation

GitHub HTML Attachment Preview

A Chrome extension (Manifest V3) that adds a Preview HTML button next to .html / .htm attachments in GitHub Pull Request and Issue comments. Clicking it fetches the attachment using your existing GitHub session and renders it in a sandboxed, isolated preview tab — no download-and-open round trip.

Built for reviewers of internal/private repositories who receive diff-explanation HTML attached to PR comments.

How it works

content script            background worker            preview page (privileged)        sandbox iframe
─────────────             ────────────────            ─────────────────────────        ──────────────
detect .html link    ──▶  fetch(url, credentials)
add "Preview HTML"        validate (status/size/type)
button                    store HTML in
on click, send URL ──▶    chrome.storage.session
                          open preview.html?id=… ──▶   read stored HTML
                                                       show metadata
                                                       postMessage(html) ─────────────▶ document.write(html)
                                                                                        (scripts run, isolated)

The content script never fetches or renders the attachment, so untrusted HTML never touches the GitHub page's DOM or origin. See DEVNOTES.md for the security model and the answers to the spec's pre-implementation questions.

Install (load unpacked)

  1. pnpm install
  2. pnpm build — outputs the unpacked extension to dist/.
  3. Open chrome://extensions, enable Developer mode (top right).
  4. Click Load unpacked and select the dist/ folder.
  5. Re-run pnpm build after code changes, then click the reload icon on the extension card.

Usage

  1. Open a GitHub PR or Issue that has a .html / .htm file attached to a comment.
  2. A small Preview HTML button appears next to the attachment link.
  3. Click it. A new tab opens showing the file's metadata (filename, source URL, fetch time) and the rendered HTML inside an isolated sandbox.

Development

Command Purpose
pnpm dev Vite dev server with HMR (CRXJS).
pnpm build Production build to dist/.
pnpm typecheck tsc --noEmit.
pnpm test Unit tests (Vitest).
pnpm check typecheck + test + build.

Layout

manifest.json          # MV3 manifest (CRXJS rewrites the src/* paths on build)
vite.config.ts         # CRXJS plugin + explicit inputs for preview/sandbox pages
src/
  content.ts           # detect links, add buttons, observe DOM, forward clicks
  background.ts         # fetch + validate + store + open preview tab
  preview.html / .ts    # privileged page: metadata + broker to sandbox
  sandbox.html / .ts    # sandboxed renderer (scripts run, fully isolated)
  shared/               # config, detect, validate, messages, storage, format
test/                  # unit tests for detect + validate
examples/sample.html   # manual-test fixture (inline script, alert, ext. image)

Manual testing

  1. Build and load unpacked (above).
  2. Open a PR/Issue in a private repo you have access to.
  3. Attach examples/sample.html (or any .html) to a comment via drag & drop.
  4. Confirm a Preview HTML button appears next to the link.
  5. Click it; confirm the preview tab opens and renders the HTML.
  6. With examples/sample.html, confirm:
    • the inline-script status line shows "ran inside the isolated sandbox" (scripts execute), and
    • no alert() dialog appears (modals suppressed), and
    • the external image fails to load (network blocked).
  7. Try a file larger than 5 MB; confirm a clear "too large" error.
  8. Confirm .txt / .pdf attachments get no button.
  9. Sign out of GitHub (or use a repo you lack access to); confirm a clear "Not authorized" error instead of a silent failure.

Security

  • Attachment HTML is rendered only inside a Manifest V3 sandbox page (src/sandbox.html): opaque origin (no allow-same-origin), so it cannot read GitHub cookies/localStorage or call extension APIs.
  • Sandbox CSP blocks all network (default-src 'none', connect-src 'none') and external/eval scripts; only inline scripts run. alert/confirm are suppressed (no allow-modals); popups and forms are disabled.
  • HTML is stored in chrome.storage.session only (cleared when the browser closes); never written to disk.
  • Fetches are limited to GitHub hosts; the response is size-capped (5 MB) and rejected if clearly binary.
  • Permissions are minimal: storage, tabs, and GitHub host access only.

Known limitations

  • Detection depends on GitHub's attachment URL shape and DOM. If GitHub changes these, links may stop being detected.
  • External CSS, images, fonts, and scripts in the attachment are blocked by the sandbox CSP (no network). Self-contained HTML previews best.
  • Scripts requiring eval/new Function will not run ('unsafe-eval' is off).
  • GitHub Enterprise Server is out of scope. To enable it, add the GHE host to ALLOWED_HOST_SUFFIXES (src/shared/config.ts) and to host_permissions / content-script matches in manifest.json.
  • Firefox is out of scope.
  • Previews are not persisted: re-opening a preview tab after the browser session ends requires clicking Preview HTML again.

Future work

  • Configurable allow-list UI for GitHub Enterprise hosts.
  • Optional opt-in toggle to allow external resources (relaxed CSP) per preview.
  • Firefox / cross-browser packaging.
  • Chrome Web Store packaging and icons.

About

Chrome extension to preview .html/.htm attachments in GitHub PR/Issue comments in an isolated sandbox, without downloading.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors