Expand description
The WASM capability sandbox (#156, slice 4).
A plugin module is loaded into extism (embedding wasmtime) with no
ambient authority: WASI is disabled, so the module gets no filesystem,
clock, randomness, or network. Its entire outside-world surface is the
host functions the host registers — and the host registers a function
only if the matching capability was granted. A module that imports a
host function whose capability wasn’t granted fails to load (a
wasmtime link error): the runtime half of the capability model, paired
with the manifest-level imports↔grant check in validate_manifest.
Execution is bounded three ways — a memory cap, a wasmtime fuel cap, and a wall-clock timeout — so a runaway module is trapped, never hangs the host.
The host-function bodies here are stubs: this slice establishes the sandbox, the capability→host-function ABI, and the enforcement/metering contract. The detector and export slices replace the stubs with real, scope-checked implementations (read the foreground window, POST to the granted origin, …).
Structs§
- Sandbox
Context - Per-install context the host functions need beyond the capability scopes themselves, plus the verdict channel.
Constants§
- DEFAULT_
FUEL - wasmtime fuel ceiling per instance — belt to the timeout’s braces, so a tight CPU loop traps on fuel even if the timer thread is starved. Roughly one unit per wasm instruction; 5e8 is far above any real probe.
- DEFAULT_
MEMORY_ MAX_ PAGES - Memory ceiling for a plugin instance, in 64 KiB wasm pages. 64 pages = 4 MiB — generous for a detector/export module, tight enough that a runaway allocation traps quickly.
- DEFAULT_
TIMEOUT - Wall-clock ceiling for a single plugin call. Detectors run on a throttled interval off the scheduler tick, so 250 ms is ample for a real probe while bounding an accidental infinite loop.
- HOST_
SUPPRESS 🔒 - The host-function name a detector calls to vote “suppress the next break”. Ungated (every detector may report a verdict) and always registered, so a detector module always links against it.
Functions§
- build_
sandboxed_ plugin - Build a sandboxed plugin from
modulebytes, registering host functions only for the grantedcapabilities. WASI is off and memory / fuel / timeout are bounded (see theDEFAULT_*consts). Returns a user-facing error if the module fails to compile, link, or instantiate — including the case where it imports a host function whose capability wasn’t granted. - evaluate_
detector - Build a detector from its module + granted capabilities, run its
detect()export once, and return whether it voted to suppress (by callinghost_suppress). A module that fails to build, has nodetectexport, or traps is treated as no suppression — a broken detector never blocks a break. Pure aside from the probes the granted host functions perform. - host_
function_ name - The host-function name a capability unlocks in the
extism:host/usernamespace, i.e. the symbol a module imports to use that capability. The sandbox registers exactly these for the granted capabilities. - host_
stub 🔒 - Placeholder body for host functions whose real implementation lands in a later slice (foreground-window and the export sinks). Returns 0. Its mere presence is still gated by the capability, so registering it doesn’t widen the module’s reach.
- register_
capability 🔒 - Register the host function a single capability unlocks. All host functions
are
() -> i64booleans in this ABI; the data each one reads (the process pattern, the granted file path) is captured from the grant + context, so a module cannot influence what’s probed. - register_
probe 🔒 - Register a
() -> i64boolean host function whose answer isprobe(data).datais captured host-side from the grant/context — never supplied by the module — so the probe is scope-checked by construction. - set_
bool 🔒 - Set the single i64 output of a host function to a boolean (1/0).