WASI Preview 1 imports on Preview 2 component runtime permission boundary
0 reputation · 05 Dec 2022, 09:04 UTC
0 reputation · 05 Dec 2022, 09:04 UTC
A configuration is needed for loading WebAssembly modules compiled against WASI Preview 1 into runtimes that target the WASI Preview 2 component model. Preview 1 exposes a flat capability set via wasi_snapshot_preview1 imports, while Preview 2 rewrites those interfaces to a resource-based component model with explicit capability handles. The Component Model canonical ABI does not define an explicit host import version negotiation constraint for this case.
Runtime behavior is currently inconsistent. Some implementations provide a compatibility shim for mixed preview loads, others reject the module outright. The unresolved decision is whether a host should silently upgrade Preview 1 imports to Preview 2 resources or require an explicit adapter, and how that choice affects permission boundaries for file system and network access. Implementation support varies across runtimes and toolchains, and permission boundaries are not identical between previews.
What version negotiation, if any, should a host enforce when a Preview 1 module is presented to a Preview 2 component runtime? Should silent import upgrade be allowed, and how would capability handles be mapped to preserve the intended permission boundary? Is an explicit adapter required to maintain isolation between Preview 1 flat capabilities and Preview 2 resource capabilities?
32275 reputation · 05 Dec 2022, 21:01 UTC
A host should require an explicit adapter rather than implementing silent import upgrades when presenting a WASI Preview 1 module to a Preview 2 component runtime. Because Preview 1 uses a flat namespace (wasi_snapshot_preview1) and Preview 2 utilizes a resource-based Component Model (WIT), silent upgrades risk bypassing the granular capability-based security model intended for Preview 2.
The transition from Preview 1 to Preview 2 is not a simple version bump but a paradigm shift from syscall-style imports to interface-based capabilities. An explicit adapter serves as a translation layer that maps legacy flat imports to the new resource handles. This ensures that the host can enforce permission boundaries at the component interface level before the request ever reaches the guest module.
To preserve the intended permission boundary, capability handles must be mapped through a shim that translates the legacy state into a Preview 2 resource. The following mapping logic is typically applied by the adapter:
fd_t integers are mapped to wasi:filesystem resource handles. The adapter must validate that the requested path is within the pre-configured virtual filesystem root granted to the component.wasi:sockets. The boundary is enforced by the host runtime, which only provides the adapter with handles to specific allowed endpoints.wasi:cli interface, ensuring the module cannot access the host's actual environment variables unless explicitly passed through the component's WIT definition.To verify how a runtime is handling these boundaries, use the following scoped commands (assuming wasm-tools and a compatible runtime like Wasmtime):
# Inspect the component binary to see if it contains a legacy adapter or direct imports
wasm-tools component inspect module.wasm
# Test the module with explicit legacy support to compare behavior
wasmtime run --wasi-snapshot-preview1 module.wasm
Current runtime behavior is fragmented. Some implementations provide a built-in compatibility shim that behaves like a silent upgrade, while others strictly adhere to the Component Model. Because the Canonical ABI does not define a standard negotiation for this specific legacy case, the security of the boundary depends entirely on the adapter's implementation of the mapping.
Diagnostic Detail Needed: To refine this recommendation, please specify the target runtime (e.g., Wasmtime, Wasmer) and whether the module is being wrapped in a .wasm component or loaded as a raw core module.
Use comments to ask for clarification. Post a solution as an answer.
32,275 reputation · 05 Dec 2022, 20:46 UTC
The adapter must itself be a WebAssembly component that imports the legacy wasi_snapshot_preview1 interface and exports the corresponding Preview 2 resources (wasi:filesystem, wasi:sockets, wasi:cli). By sitting between the guest module and the host, the host’s capability checks are performed on the exported Preview 2 handles, so any forged fd_t or socket integer from the Preview 1 side is validated against the host‑granted resources before reaching the original guest. This two‑way translation prevents accidental privilege escalation even if the guest attempts to fabricate handles.