QUESTPIE

Running the supervisor

The Deno process that actually spawns guest subprocesses, the command to start it, the environment it reads, and the shared secret without which it refuses every run your app sends.

View markdown

httpSandboxAdapter never executes anything. It validates, authenticates and forwards. Everything after that, the subprocess and the clamps and the permission flags, belongs to a second process you deploy yourself.

The command

It runs under Deno only, which is why it ships as source rather than as part of your bundle. Start it as a sidecar beside the app.

export SANDBOX_HOST_ADMISSION_SECRET='at-least-32-random-bytes'
export SANDBOX_BROKER_URL='https://app.internal/api/sandbox/rpc'

deno run --allow-net --allow-env --allow-run --allow-read \
  --allow-write=$TMPDIR \
  node_modules/@questpie/sandbox/src/sandbox-server.ts

It listens on PORT, default 8787, and exposes exactly two endpoints, GET /health and POST /run. Point the app's SANDBOX_URL at its origin, with no path or query, or the adapter rejects the URL before it sends anything.

Environment

VariableWhat it does
PORTListen port, default 8787
SANDBOX_HOST_ADMISSION_SECRETShared with the adapter, at least 32 bytes. Without a match, /run returns 403
SANDBOX_BROKER_URLThe one broker URL it will relay guest app calls to
DENO_BINDeno binary for guest subprocesses, defaults to the supervisor's own executable
SANDBOX_DISABLE_NETNS_FIREWALLSet to 1 to skip the Linux network namespace layer

No secret means no runs, not unauthenticated runs

Every ctx.executor.run() arrives as a host-mode /run. One carrying no credential, or a secret under 32 bytes, or one that does not match byte for byte, is refused before a subprocess is spawned. Set the same value on both sides or the sandbox is inert.

The broker URL is checked, not trusted

Any run that carries bindings is compared against SANDBOX_BROKER_URL before the spawn. A mismatch in protocol, host, effective port, path or query is a denial, and userinfo and fragments are forbidden outright. This is what stops a spoofed caller from redirecting the supervisor, carrying the per-run token, to a host it chose. Point it at your app's own internal address.

The Linux egress layer

On Linux with unshare, nft and ip present and the capabilities to use them, each run also gets its own network namespace with a default-drop nftables ruleset that drops private ranges and accepts only the validated public allowlist. Off Linux, or when a tool or capability is missing, it logs a one-line notice and the run proceeds without it.

Treat it as a second layer. The subprocess permission flags are the boundary that is always there, and the ruleset logic is unit-tested while the actual kernel drop is only verified on a real Linux worker.

Remote workloads

httpSandboxAdapter also exposes runWorkload({ envelope }), a separate path where the source, input and capabilities come from a consumer-supplied authorizer rather than from your call site. It is authenticated by its own signed admission rather than by the host secret, and it reads three more variables: SANDBOX_WORKLOAD_ADMISSION_SECRET, SANDBOX_WORKLOAD_ADMISSION_KEY_ID and SANDBOX_INSTANCE_ID.

SANDBOX_INSTANCE_ID is a process incarnation, not a deployment or replica name. Generate a new one for every supervisor process and every restart, and address that process directly, because the admission is bound to it and its replay state is process-local.

Next

Sandbox is the adapter side, the capability manifest and the run result.

On this page