Skip to content

Environment Variables

The sandboxed process starts with an empty environment. Not your shell’s environment minus some entries — empty, plus whatever policy adds.

env {
passthrough ["HOME", "USER", "LANG", "LC_*"]
set ["TERM=xterm-256color"]
set_default ["EDITOR=vi"]
deny ["*_TOKEN", "AWS_*", "LD_PRELOAD", "DYLD_INSERT_LIBRARIES"]
}
passthroughcopy this variable from your environment, if it is set
setset it to this literal value
set_defaultset it only if nothing else already did
denyremove it, whatever set it

Patterns may contain *, matching any run of characters: LC_*, *_TOKEN, npm_config_*. There is no ** — variable names are a flat namespace.

Applied in this order, so later beats earlier:

passthrough → set → (wardcell's runtime vars) → set_default → deny

deny is applied last, so it beats everything including wardcell’s own runtime variables. That is deliberate: the names most worth denying are exactly the ones an attacker would try to reintroduce.

set_default runs after wardcell’s runtime variables, so it can never accidentally override anything wardcell set for the run.

Less than you might expect — and nothing at all where egress is captured transparently.

Proxy routing variables (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY) are set in exactly one case: the macOS proxy-variable fallback, where the client has to route itself to the proxy. Everywhere else — Linux, and macOS under transparent capture — the flow is intercepted below the client, so telling it about a proxy would be wrong (it would dial the proxy’s own port and be captured twice). In those modes wardcell injects no routing variables. You do not write these; a deny on them breaks egress in fallback mode.

CA-trust variables are never injected automatically. The variable a client reads its CA from is a property of that tool — NODE_EXTRA_CA_CERTS means nothing to cargo, CARGO_HTTP_CAINFO nothing to node — so setting one globally would set it for every run whether or not that tool is present. Instead the tool’s own fragment points its variable at the per-run CA:

env {
set ["NODE_EXTRA_CA_CERTS=$WARDCELL_PROXY_CA_CERT"]
}

$WARDCELL_PROXY_CA_CERT (and its bundle / truststore / SPKI forms) expands to the per-run CA at a path this sandbox can open, but only when the policy grants network. The bundled toolchain fragments already carry the right one for each tool, so you rarely write this yourself. See the full list of these variables.

An empty default is the whole point: a token in your shell does not reach the sandbox unless a fragment names it.

env {
passthrough ["PATH", "HOME", "TERM"]
deny ["*_TOKEN", "*_SECRET", "*_KEY", "AWS_*", "GITHUB_*"]
}

The deny list is belt-and-braces — nothing passes those through — but it means a later fragment adding passthrough ["*"] cannot reintroduce them.

If a tool genuinely needs a credential, prefer a zone: the proxy attaches it to the outbound request and the sandboxed process never holds it at all.