Skip to content

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

Description

@NathanFlurry

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions