2.4 KiB
preopens
(no submodules)
Purpose
Maps policy.fs[] rules onto a WASI preopen table. The WASI capability
model is file-descriptor-based: a guest can only open paths reachable
from a preopened directory, and the host controls whether each preopen
is read-only or read-write. This module owns that translation.
Paths outside the policy allowlist are NOT preopened, so the guest's
path_open cannot reach them — denial is enforced by the absence of
the preopen, not by a runtime check. Write access requires the rw:
rule prefix; the default is read-only.
Features
rw:prefix promotes a preopen to read-write; absence keeps it read-only.- Globs
/*and/**are stripped because WASI preopens are directory-granular — file-level scoping is enforced by the WASI runtime's resolved-path check. - Deduplication: duplicate rules collapse, with
rwwinning overro. matchPreopenreturns the preopen forpath_opengating, orundefinedfor a miss / write-against-ro.
Usage: Basic
import {
buildWasiPreopens,
resolvePermissionPolicy,
} from "@suaveplan/api-sandbox-wasm";
const policy = resolvePermissionPolicy({ fs: ["./uploads/*", "rw:./tmp"] });
const preopens = buildWasiPreopens(policy);
Usage: Advanced
import { matchPreopen } from "@suaveplan/api-sandbox-wasm/preopens";
const matched = matchPreopen(preopens, "/abs/host/path/to/file", "rw");
if (matched === undefined) {
metrics.permissionDenied("fs", "preopen_miss_or_ro");
throw new SandWasmError(SAND_WASM_CODES.PREOPEN_DENIED, "denied");
}
API Reference
buildWasiPreopens(policy): readonly WasiPreopen[]matchPreopen(preopens, hostPath, "ro" | "rw"): WasiPreopen | undefinedWasiPreopen.{guestPath, hostPath, mode}
Implementation Notes
hostPath is computed via node:path.resolve, anchoring relative
rules against process.cwd() AT POLICY-BUILD TIME — operators must
build the policy in the directory the plugin expects to see. The
resolved path is used as the dedup key; rules that produce the same
absolute path collapse, with rw winning over ro because privilege
escalation is more visible than silent downgrade.
WASI's preview1 file-rights bitmask is rich (read, write, allocate, truncate, etc.) — the implementation here intentionally uses a two-state mode so policy authoring stays readable. Sites that need finer granularity should layer their own bitmask check on top.