Skip to content

Conversation

@guerler
Copy link
Contributor

@guerler guerler commented Aug 10, 2025

GHOST is a Galaxy visualization that securely loads and displays static websites packaged
as ZIP-based QIIME 2 visualization (.qzv) files or similar archive formats. The archive is
fetched at runtime, unzipped in memory, and its contents are served to an embedded iframe
via a service worker. HTML files are automatically rebased so all relative paths resolve
through the service worker scope.

The service worker enforces a strict same-origin policy:

  • Only GET requests within the defined virtual scope are served.
  • Files are only returned if explicitly loaded into the in-memory virtual file system.
  • Any other same-origin requests (for example, /api/version) are blocked with a 403
    Forbidden response to prevent malicious HTML content from interacting with the Galaxy API.

This enables arbitrary client-side visualizations to run isolated from the main Galaxy UI,
while still loading all assets locally from the extracted archive.

Some example archives you can load:
https://raw.githubusercontent.com/qiime2/q2-fmt/master/demo/raincloud-baseline0.qzv
https://docs.qiime2.org/2024.2/data/tutorials/moving-pictures/core-metrics-results/faith-pd-group-significance.qzv
https://raw.githubusercontent.com/caporaso-lab/q2view-visualizations/main/uu-fasttree-empire.qzv


// Only handle same-origin requests
if (isSameOrigin) {
if (event.request.method === "GET" && url.pathname.startsWith(scoped)) {
Copy link
Member

Choose a reason for hiding this comment

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

get requests include the session key, this might be a concern. How does the interception work, can a script that's loaded through the worker makes requests using their own shipped networking library ? Have you tried exploiting this with malicious archives ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am experimenting with an option that injects the actual dataset and sandboxes the entire visualization. This would limit the file size, which is a drawback, but likely make it safe fyi.

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.

2 participants