rivet-dev / rivet-dev/dynamic-apps
Disable guest WebAssembly by default; add an opt-in permission
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1k
- Forks
- 51
- Avg merge
- 6m
- Merged PRs (30d)
- 13
Description
Summary
Make guest WebAssembly disabled by default, and add a permission scope users opt into to re-enable it (consistent with our deny-by-default permission posture).
Motivation
Today the guest WebAssembly API is always available in the V8 isolate (runtime-platform docs: "WebAssembly stays available on every tier"). There is currently no way to disable it (no expose_wasm / jitless flag plumbed through the runtime).
WebAssembly grants the guest no additional capability over JavaScript (both are isolate-confined, have no ambient authority, and route all I/O through the kernel), and the classic side-channel vector (Spectre via SharedArrayBuffer + high-resolution timers) is already mitigated by default by timingMitigation: "freeze" (removes SharedArrayBuffer, freezes timers).
The remaining, legitimate concern is V8 JIT/compiler attack surface: the WASM compiler is large and complex, and WASM JIT bugs have historically been used for in-isolate memory-corruption → sandbox escapes. For maximally-untrusted workloads, being able to remove that surface is valuable defense-in-depth. Since we are deny-by-default everywhere else, WASM should follow the same model.
Proposed design
- Add a permission scope, e.g.
permissions: { webAssembly: "allow" | "deny" }, deny by default. - When denied, the guest's
WebAssemblyglobal is unavailable (and ideally the isolate runs without the WASM compiler / jitless where feasible) so the JIT attack surface is actually removed, not just the global hidden. - Plumb through
CreateVmConfigon the wire and expose on both the TypeScript client (NodeRuntime/secure-exec) and the Rust client (per the wire/client-parity rule). - Update the
runtime-platformdocs: note WASM is off by default for hardening, how to opt in, and the security rationale (no extra capability; side-channels already mitigated; this reduces JIT attack surface).
Tradeoff to weigh during design
Some real npm packages ship WASM internally (certain crypto/compression/image/parsing libs). Deny-by-default will break those unless the user opts in, so the opt-in must be easy and clearly documented. (If default-off proves too disruptive in practice, the fallback is default-on with an easy opt-out, but the issue as filed requests default-off + opt-in.)
Notes
- Distinct from the WASI command runtime that runs
sh/coreutils (those are separate WASM binaries the sidecar runs); this is specifically the guest'sWebAssemblyglobal.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing CreateVmConfig on the wire and how permissions reach the NodeRuntime/secure-exec TypeScript client and Rust client. Review the runtime-platform documentation and the existing deny-by-default permission model. Done means guest WebAssembly is disabled by default, an opt-in scope works across both clients, and the security rationale and npm-package tradeoff are documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, typescript, wasm
- Domain
- backend-api-design, documentation, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100