Network Firewall
Control agent network egress with domain and IP-based rules
This is an experimental feature. The configuration and behavior may change in future releases.
The network firewall controls outbound network traffic from your agent sandbox. It protects against prompt injection attacks and data exfiltration by allowing you to specify exactly which domains and IP addresses your agent can access.
Prerequisites
Network firewall requires the VM0 production runner. Add experimental_runner with group: vm0/production to your configuration before enabling the firewall.
Quick Start
Enable the firewall with a simple allowlist:
version: "1.0"
agents:
my-agent:
framework: claude-code
experimental_runner:
group: vm0/production
experimental_firewall:
enabled: true
rules:
- domain: "*.github.com"
action: ALLOW
- final: DENY
environment:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}Configuration Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
enabled | boolean | Yes | - | Enable network firewall |
rules | array | No | [] | List of firewall rules |
experimental_mitm | boolean | No | false | Enable HTTPS traffic inspection |
experimental_seal_secrets | boolean | No | false | Encrypt secrets (requires MITM) |
Rule Types
Domain Rules
Match traffic by domain name:
rules:
- domain: "api.github.com"
action: ALLOWMatching behavior:
- Exact match:
api.github.commatches onlyapi.github.com - Wildcard:
*.github.commatchesapi.github.com,raw.github.com, and alsogithub.comitself - Case-insensitive:
GitHub.commatchesgithub.com
IP Rules
Match traffic by IP address or CIDR range:
rules:
- ip: "192.168.1.100"
action: ALLOW
- ip: "10.0.0.0/8"
action: DENYSupported formats:
- Single IP:
1.2.3.4 - CIDR ranges:
10.0.0.0/8,192.168.0.0/16,172.16.0.0/12
Terminal Rules
Set a default action for unmatched traffic:
rules:
- domain: "*.allowed.com"
action: ALLOW
- final: DENY # Block everything elseThe final rule stops evaluation and returns the specified action.
Rule Evaluation
Rules are evaluated top to bottom with first-match-wins semantics:
- Each outgoing connection is checked against rules in order
- The first matching rule determines the action (ALLOW or DENY)
- If no rule matches, traffic is denied by default (zero-trust)
The platform automatically allows essential domains (*.vm0.ai, *.cloudflarestorage.com, and your model provider) before your rules are evaluated.
Auto-Injected Rules
The following domains are automatically allowed to ensure agent functionality:
| Domain | Purpose |
|---|---|
*.vm0.ai | VM0 platform communication |
*.cloudflarestorage.com | Volume and artifact storage |
*.anthropic.com | Claude API (for claude-code provider) |
*.openai.com | OpenAI API (for codex provider) |
These rules are prepended to your custom rules and cannot be overridden.
Operating Modes
SNI-Only Mode (Default)
The default mode filters traffic at the TLS handshake using Server Name Indication (SNI):
experimental_firewall:
enabled: true
# experimental_mitm: false (default)Characteristics:
- Filters based on hostname in TLS ClientHello
- No decryption of HTTPS traffic
- Blocked connections fail with TLS certificate error
- Lower overhead, simpler setup
MITM Mode
Enable full HTTPS inspection for detailed logging and control:
experimental_firewall:
enabled: true
experimental_mitm: trueCharacteristics:
- Decrypts and inspects all HTTPS traffic
- Blocked requests return HTTP 403 with "Blocked by firewall"
- Detailed network logs include URL, method, status, latency
- Higher overhead, requires CA certificate trust
Secret Sealing
Encrypt environment secrets to prevent exfiltration:
experimental_firewall:
enabled: true
experimental_mitm: true
experimental_seal_secrets: trueSecret sealing requires MITM mode to be enabled.
Viewing Network Logs
View firewall activity using the CLI:
vm0 logs <runId> --networkOptions:
--tail N- Show last N entries (default: 5, max: 100)--head N- Show first N entries--since TIME- Filter by time (e.g.,5m,2h,2024-01-15T10:30:00Z)
SNI mode output:
[2024-01-15T10:30:00] SNI ALLOW api.github.com:443 domain:*.github.com
[2024-01-15T10:30:01] SNI DENY evil.com:443 final:DENYMITM mode output:
[2024-01-15T10:30:00] GET 200 150ms 2.3KB/45KB https://api.github.com/repos
[2024-01-15T10:30:01] POST 403 5ms 1.2KB/0B https://evil.com/exfil (BLOCKED)Example Configurations
Allowlist Pattern
Only allow specific domains, deny everything else:
experimental_firewall:
enabled: true
rules:
- domain: "*.github.com"
action: ALLOW
- domain: "*.npmjs.org"
action: ALLOW
- domain: "registry.npmjs.org"
action: ALLOW
- final: DENYBlocklist Pattern
Block specific networks, allow everything else:
experimental_firewall:
enabled: true
rules:
- ip: "10.0.0.0/8"
action: DENY
- ip: "192.168.0.0/16"
action: DENY
- ip: "172.16.0.0/12"
action: DENY
- final: ALLOWCorporate Environment
Block internal networks and allow only approved external services:
experimental_firewall:
enabled: true
experimental_mitm: true
rules:
# Block internal networks
- ip: "10.0.0.0/8"
action: DENY
- ip: "192.168.0.0/16"
action: DENY
# Allow approved services
- domain: "*.github.com"
action: ALLOW
- domain: "*.githubusercontent.com"
action: ALLOW
- domain: "*.npmjs.org"
action: ALLOW
- domain: "*.pypi.org"
action: ALLOW
# Deny everything else
- final: DENY