2.5 KiB
outbound
(no submodules)
Purpose
Builds the outbound-socket allowlist from policy.fetch[] and wraps the
host's connect adapter so denied destinations are refused BEFORE any
OS socket is opened. Denial raises SAND_WASM_OUTBOUND_DENIED and
fires the injected onDeny hook so the sandbox host can increment
plugin.permission_denied_total{capability="fetch"} without coupling
this module to the OTel API.
The matcher supports exact hosts, *.suffix wildcards (RFC 6125
semantics — the apex suaveplan.io does NOT match *.suaveplan.io),
and optional port suffixes. Bare-host rules match any port; port-pinned
rules match only the named port.
Features
- Exact-host and
*.suffixrule patterns. - Port-pinned rules (
api.stripe.com:443). - Default destination port 443 when none is supplied.
- O(rules) matching — no regex compilation, suitable for the typical small allowlists.
gateOutboundConnectwraps a hostconnectadapter; denied calls never invoke the inner adapter.
Usage: Basic
import { buildWasiOutboundAllowlist } from "@suaveplan/api-sandbox-wasm";
const allowlist = buildWasiOutboundAllowlist(policy);
if (!allowlist.isAllowed("api.stripe.com")) { /* deny */ }
Usage: Advanced
import { gateOutboundConnect } from "@suaveplan/api-sandbox-wasm/outbound";
const gated = gateOutboundConnect(
allowlist,
async (destination) => net.connect(destination),
(destination) => instruments.recordPermissionDenied("fetch", destination)
);
const socket = await gated("api.stripe.com"); // throws SAND_WASM_OUTBOUND_DENIED for non-listed hosts.
API Reference
buildWasiOutboundAllowlist(policy): OutboundAllowlistgateOutboundConnect<TSocket>(allowlist, connect, onDeny)OutboundAllowlist.{isAllowed(destination), rules}
Implementation Notes
Wildcards live inside a single *.suffix form rather than full glob
matching because RFC 6125 wildcard semantics are well-defined and
predictable. Adding nested wildcards (e.g. **.example.com) would
require careful escape handling that this module does not attempt; if
operators need deeper granularity they should enumerate sub-domains
explicitly.
Out-of-range port suffixes (>65535) on RULES are treated as host-only — the parser falls back to the bare-host path rather than throwing, because a parse failure here would be operator-visible during host boot and add no security value. Out-of-range ports on DESTINATIONS are treated as the default 443 for the same reason.