wasi_preview1 (wasm v0.1.0)

View Source

WASI Preview 1, as an Erlang host interface.

Build an import map here when you want to choose exactly what a WASI program may reach. This is not an embedded WASI runtime: each syscall is an ordinary Erlang host function, so you can inspect it, trace it, replace it or refuse it, and the capability decisions are made in Erlang rather than inside somebody else's C library.

Grant capabilities explicitly, because nothing is ambient

Wasi = #{ stdout => group_leader(),
          dirs   => [{<<"/data">>, "/srv/app/data", read}],
          env    => #{<<"MODE">> => <<"production">>},
          args   => [<<"prog">>, <<"--flag">>],
          clocks => [monotonic],
          random => strong,
          net    => #{connect => [{tcp, <<"10.0.0.0/8">>, 443}]} },
{ok, Imports} = wasi_preview1:imports(Wasi).

Leave a key out and the module does not have that capability: the syscall returns ENOTCAPABLE. No dirs means no filesystem at all, not one rooted at the current directory. No net means no network at all, not a network restricted to somewhere sensible. No env means environ_get reports zero variables rather than leaking the host's. That is the opposite of the usual default, and it is the point: a module gets what you gave it and nothing else.

wasi_net parses the network grant, and wasi_sock runs the sockets behind it. docs/security.md says what a grant does not cover.

ENOTCAPABLE stays distinct from EACCES throughout, so the module (and whoever is debugging it) can tell "you were not granted this" from "the host operating system refused".

Path resolution, which is where sandboxes actually fail, is in wasi_path.

Summary

Functions

Close every descriptor this instance still holds.

Pull the exit status out of the error proc_exit produces.

Build the import map, under a module name you choose. Pass wasi_unstable to bind the same implementation for an older toolchain.

Functions

close_all(Inst)

-spec close_all(term()) -> ok.

Close every descriptor this instance still holds.

Registered as an instance cleanup, so wasm:destroy/1 runs it. A guest that exits without closing its files and sockets is ordinary, and dropping the handles only makes them unreachable: the operating system resources stay until the owning process exits. Preopens are closed here too. Refusing to close one is a rule about the guest asking, not about teardown.

default_config()

-spec default_config() -> map().

exit_code/1

-spec exit_code(term()) -> {ok, integer()} | error.

Pull the exit status out of the error proc_exit produces.

imports(Config)

-spec imports(map()) -> map().

imports(Config0, ModuleName)

-spec imports(map(), binary()) -> map().

Build the import map, under a module name you choose. Pass wasi_unstable to bind the same implementation for an older toolchain.