Skip to content

fix: load an inlined WASM without fetch so a strict CSP works - #196

Open
livenson wants to merge 2 commits into
coder:mainfrom
waldur:fix/wasm-data-url
Open

livenson wants to merge 2 commits into
coder:mainfrom
waldur:fix/wasm-data-url

Conversation

@livenson

Copy link
Copy Markdown

Summary

Closes #188.

Library builds inline ghostty-vt.wasm as a base64 data: URL, and Ghostty.load() fetched that URL. Under a Content-Security-Policy whose connect-src does not include data: (for example connect-src 'self'), the fetch is blocked and logs a violation. The loader then falls back to ./ghostty-vt.wasm and /ghostty-vt.wasm, which resolve against the page and usually 404, so init() failed and offered no way to point it at the file.

Change

  • Ghostty.load() decodes base64 data: URLs in memory instead of fetching them. The bundled WASM now loads with no network request and no CSP exception, and the fallback probes no longer run for bundled builds. Loading from file paths and URLs is unchanged.
  • init(wasmPath?) forwards an explicit path to Ghostty.load(), for embedders who serve dist/ghostty-vt.wasm themselves (suggestion 1 in CSP: wasm loads via data: URI fetch (blocked by connect-src 'self') and init() offers no wasm path override #188).
  • README: a short Content-Security-Policy section, including the 'wasm-unsafe-eval' requirement (suggestion 3).
  • Not changed: the WASM is still inlined in the bundle (the size point in suggestion 2); that is a build decision this PR leaves alone.

Testing

  • lib/ghostty-load.test.ts: loading from a data: URL succeeds while fetch rejects, and fetch is never called.
  • bun run fmt && bun run lint && bun run typecheck && bun test && bun run build all pass, with tests run against a WASM built from this tree (Zig 0.15.2).
  • In headless Chromium, the built library on a page served with default-src 'none'; script-src 'self' 'wasm-unsafe-eval'; connect-src 'self' initializes with no CSP violation and no request for a .wasm file. With the npm 0.4.0 build, the same page logs the data: violation and requests the fallbacks.

Library builds inline ghostty-vt.wasm as a data: URL, and Ghostty.load()
fetched that URL. A page whose Content-Security-Policy connect-src does
not include data: blocks the fetch, logs a violation, and the loader then
probes ./ghostty-vt.wasm and /ghostty-vt.wasm over the network, both of
which usually 404.

Decode base64 data: URLs in memory instead. No network request is made,
no CSP exception is needed, and the fallback probes no longer run for
bundled builds. Loading from file paths and URLs is unchanged.
Ghostty.load() already accepts an explicit path, but init() did not pass
one through, so embedders serving dist/ghostty-vt.wasm themselves had no
way to point the loader at it. Forward an optional wasmPath from init().

Add a Content-Security-Policy section to the README: the bundled WASM
needs no connect-src exception, and compiling WebAssembly requires
'wasm-unsafe-eval' in script-src.
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.

CSP: wasm loads via data: URI fetch (blocked by connect-src 'self') and init() offers no wasm path override

1 participant