Herbarium: a Tauri 2 app that runs untrusted AI-generated HTML in a sandboxed reader
I (and some agents: claude, gpt, deepseek, gemini) just shipped the first release of Herbarium, a Tauri 2 + Svelte 5 app for keeping the HTML pages LLMs generate and bringing them back for review.
The interesting part on the Tauri side was running untrusted HTML safely:
\- Pages are served over a custom \`herbarium://\` URI scheme (registered as an async protocol so a rescan never blocks the UI thread), with a Content-Security-Policy injected by the backend per page \- They render in an \`<iframe sandbox="allow-scripts allow-popups">\` without \`allow-same-origin\`, so they can't reach the app or IPC \- Navigation guard: the main window is built manually with \`WebviewWindowBuilder\` so \`on\_navigation\` and \`on\_new\_window\` can block any frame navigation outside the app; on Windows I also needed a WebView2 frame-navigation hook, because subframe navigations bypass the regular one \- Network access is a per-page switch that swaps the CSP between "nothing" and "a CDN allowlist"
A couple of Tauri things I learned the hard way:
\- The bundler reads \`bundle.createUpdaterArtifacts\` from the config passed with \`--config\`, not from the \`TAURI\_CONFIG\` env var: my CI built "successfully" with zero updater signatures until I noticed \- On Wayland, an undecorated window gets a client-side titlebar from tao; creating it visible triggers a GTK "set\_titlebar on a realized window" warning. Creating it hidden and calling \`show()\` after setup fixes it
Repo (MIT): [https://github.com/abdoufermat5/herbarium](https://github.com/abdoufermat5/herbarium)
Happy to go deeper on any of this, or to hear how others sandbox user content in Tauri.