rivet-dev / rivet-dev/dynamic-apps

Disable guest WebAssembly by default; add an opt-in permission

Open
#91 0 comments 0 reactions 0 assignees View on GitHub

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 WebAssembly global 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 CreateVmConfig on 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-platform docs: 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's WebAssembly global.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.