Skip to content

Egress

A sandboxed workload reaches the network only through an allowlist proxy. There are two modes. Guest mode is the default: the proxy runs inside the VM and iptables forces traffic through it. Broker mode is opt-in (PAL_EGRESS_MODE=broker, Firecracker only): the VM has no network device, every request crosses a vsock to a broker in the runtime manager, and the broker adds the credential on the host. If your workload calls an API with a key, broker mode is the one where a compromised workload never holds that key.

A workload sends requests to the harness proxy on 127.0.0.1:3128. In guest mode iptables forces traffic through it; in broker mode the proxy forwards over vsock to a host broker. Both check the allowlist: allowed requests go upstream, refused ones are denied and audited.A workload sends requests to the harness proxy on 127.0.0.1:3128. In guest mode iptables forces traffic through it; in broker mode the proxy forwards over vsock to a host broker. Both check the allowlist: allowed requests go upstream, refused ones are denied and audited.
Guest mode (default) Broker mode
Where the allowlist is enforced Inside the VM, by the harness proxy On the host, in the runtime manager
Network device in the VM Yes None. The only channel out is vsock
What forces traffic through the proxy An iptables REDIRECT to 127.0.0.1:3128, installed by the VM image Nothing needed: there is no other route
A client that ignores HTTP_PROXY Still caught, if the REDIRECT rule is installed Has no route
Credentials Vended into the VM (Identity and secrets) Injected on the host; never in the VM
Backends Firecracker and others Firecracker only

In guest mode the proxy is advisory unless the REDIRECT rule exists. The harness checks for the rule at boot. When egress rules are declared and the rule is missing, production (PAL_ENV=production|staging) refuses to start the workload, and an explicit PAL_EGRESS_FAIL_CLOSED=0 is ignored with a warning. In dev, PAL_EGRESS_FAIL_CLOSED=1 opts in to the same refusal; otherwise the harness logs a security warning and an egress_preflight audit event.

  1. The workload sends an ordinary HTTP(S) request through 127.0.0.1:3128. The harness sets HTTP_PROXY and HTTPS_PROXY, so most clients need no change.
  2. The harness (PID 1) forwards the bytes over vsock to the host.
  3. The broker matches the destination against the sandbox’s allowlist.
  4. If the rule has an inject entry (header, secret_uri, optional value_prefix), the broker resolves the secret on the host and replaces any placeholder header the workload sent.
  5. The request goes upstream. A denied request is refused and written to the audit stream.
Recorded on a real Firecracker VM, opt-in broker mode
  1. Looks for a network card
    noneThe VM has no network device. Its only way out is a socket to the host.
  2. Calls an API with the key “placeholder”
    200The host swapped in the real credential. The API accepted it; the agent only ever saw “placeholder”.
  3. Sends the same call over plain HTTP
    403Refused by the host. A credential never leaves unencrypted.
Every broker check in the run passed. Replayed from the test’s own output.Watch the recording ›

Each spawn declares its egress rules: a host pattern, HTTP methods and a rate. Anything not listed is denied. The broker also refuses private, loopback, link-local (including 169.254.169.254) and similar internal ranges, and allows only port 443 unless PAL_EGRESS_ALLOWED_PORTS lists others. Denials are security-critical audit events: the harness logs them locally before forwarding and does not drop them during a short manager outage.

A spec names a secret by secret_uri, never by value. The broker resolves it on the host at request time, so the value exists only on the host side of the vsock. It does not enter the guest, logs or audit events, and inject specs are stripped from the spawn contract the guest reads.

  • HTTPS. The broker terminates TLS only for hosts whose rule injects a credential, using a per-VM ephemeral CA that is name-constrained to those hosts. Every other host is an opaque CONNECT tunnel with end-to-end TLS.
  • Plain HTTP. Injection over plain HTTP is refused with 403 unless PAL_EGRESS_PLAIN_INJECT=1 and the port is 80.
  • Binding. An injected request must target the exact approved host, and rules that inject must be exact hostnames, not wildcards.
  • Tenant scope. The secret ref resolves with the VM’s own tenant.

Broker mode can scan outbound request headers and the start of the body (64 KiB by default, 1 MiB ceiling) for payment cards (Luhn-checked), secret keys (AWS, GitHub, Slack, PEM), emails, phones and your own RE2 patterns (ADR 0030). Each rule runs in off, audit or block mode. A block returns 403 with the header X-Pal-Reason: dlp-block. Rules are per tenant (GET and PUT /v1/egress/dlp-policy, POST /v1/egress/dlp-policy/rules) and are fixed when a VM is scheduled.

infra/firecracker/broker-e2e.sh runs three requests from inside a broker-mode Firecracker VM:

The agent What happens
Looks for a network card There is none. The only channel out is vsock.
Calls an allowlisted API with the header value placeholder The host swaps in the real credential and the API answers 200. The agent only saw “placeholder”.
Sends the same call over plain HTTP The host refuses it with 403. A credential never leaves unencrypted.

Watch the recording (KVM host, real Firecracker).

  • Broker mode is not the default, and Kata and Kubernetes backends do not support it.
  • Guest mode is only as strong as the image’s iptables rule. See Security model for the other known gaps.
  • The allowlist controls where a workload can connect. It does not inspect what an allowed host receives, beyond DLP in broker mode.

Related: Identity and secrets, Isolation.