Files
skills/docs/api-stack/api/api-sandbox-wasm/src/preopens/preopens.md
2026-05-29 08:20:56 +01:00

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 rw winning over ro.
  • matchPreopen returns the preopen for path_open gating, or undefined for 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 | undefined
  • WasiPreopen.{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.