Skip to content

Network egress policy

Network access is a sandbox capability. Treat it like filesystem writes or secret grants: start closed, add the smallest destination set that makes the workload useful, and record why the grant exists.

This page focuses on outbound egress. For backend network layout and port forwarding mechanics, see Networking.

LevelUse whenExample
No egressGenerated code, code interpreters, offline analysis.--network-preset none
Package registriesBuild or install steps need language registries.--network-preset registries
Local developmentA developer needs common dev services.--network-preset dev
Explicit allowlistProduction-like agent or service path.--network-allow api.example.com:443
UnrestrictedLocal debugging only.Avoid for untrusted workloads.

For security-sensitive examples, use no egress or explicit allowlists. Broad presets are convenience tools, not production policy.

Start closed:

Terminal window
mvmctl up --flake . --name agent-sandbox --network-preset none

Allow only package registries for install-heavy workflows:

Terminal window
mvmctl up --flake . --name build-sandbox --network-preset registries

Allow named destinations:

Terminal window
mvmctl up --flake . --name agent-sandbox \
--network-preset none \
--network-allow api.openai.com:443 \
--network-allow github.com:443

Keep inbound ports separate from outbound egress:

Terminal window
mvmctl up --flake . --name api-dev \
--network-preset none \
-p 127.0.0.1:8080:8080

Opening a host port does not mean the guest should have outbound internet access.

Static declarations should make network posture reviewable:

network=mvm.network(mode="none")

For a reviewed outbound grant:

network=mvm.network(
mode="bridge",
egress=mvm.egress([
mvm.host_port("api.openai.com", 443),
]),
dns=mvm.dns_system(),
)

Use Declaration cookbook for the full decorator shape.

Do not let a model choose arbitrary network destinations. The application should map a capability to a fixed grant:

{
"tool": "web_fetch",
"network": {
"mode": "bridge",
"allow": [
{
"host": "api.openai.com",
"port": 443
}
]
}
}

Validation rules:

  • reject wildcard hosts, CIDRs, and user-provided raw proxy URLs unless the policy explicitly supports them;
  • allow only expected ports for each tool capability;
  • keep DNS policy explicit when the workload depends on names;
  • store the grant decision with the audit/run identifier;
  • return policy denial distinctly from transport or guest command failure.

Browser and desktop automation should be treated as high-risk network users. They may carry cookies, sessions, downloads, and rendered user data.

Use a dedicated profile:

  • no broad host mounts;
  • short TTL;
  • explicit egress allowlist;
  • isolated persistent workspace if state must survive;
  • no credential-bearing browser profile unless the task requires it;
  • cold state or snapshots retained only with a clear retention rule.

The enforcement mechanism is backend-specific:

  • Linux Firecracker paths can enforce bridge traffic with host firewall rules.
  • macOS backends enforce through their host-side network layer.
  • Some local debugging backends may have weaker isolation tiers.

Docs and examples should describe the product policy first, then name backend limits where the mechanism matters. Do not turn a backend convenience path into a product security claim without tests and claim-ledger evidence.

Before allowing egress:

  • name the exact host and port;
  • confirm why the workload needs it;
  • confirm whether DNS is needed;
  • confirm whether the destination can receive secrets or user data;
  • confirm logs and receipts will not expose payload data;
  • confirm cleanup or retention behavior for any downloaded files.