Skip to main content
Each sandbox runs in its own Linux network namespace with a dedicated TAP device and veth pair. Outbound traffic passes through a Layer-7 TCP proxy that enforces your network policy before packets reach the internet.

Default behavior

By default, sandboxes have unrestricted outbound internet access. Any domain or IP is reachable.

Block all outbound traffic

ALL_TRAFFIC is a constant equal to "0.0.0.0/0". Adding it to deny_out blocks everything.
from declaw import Sandbox, ALL_TRAFFIC

sbx = Sandbox.create(
    network={"deny_out": [ALL_TRAFFIC]}
)

# This will fail — no outbound traffic allowed
result = sbx.commands.run("curl -s https://example.com")
print(result.exit_code)  # non-zero

Domain allowlist

Allow only specific domains and block everything else.
from declaw import Sandbox, ALL_TRAFFIC

sbx = Sandbox.create(
    network={
        "allow_out": ["api.openai.com", "pypi.org"],
        "deny_out": [ALL_TRAFFIC],
    }
)

# This works — pypi.org is allowed
result = sbx.commands.run("pip install requests")

# This is blocked
result = sbx.commands.run("curl -s https://google.com")

Wildcard domain matching

Use *. prefix to match all subdomains.
sbx = Sandbox.create(
    network={
        "allow_out": [
            "*.openai.com",        # api.openai.com, platform.openai.com, etc.
            "*.anthropic.com",     # api.anthropic.com, etc.
            "*.github.com",        # api.github.com, raw.githubusercontent.com, etc.
            "pypi.org",            # exact match only
        ],
        "deny_out": [ALL_TRAFFIC],
    }
)
When domain filtering is enabled, DNS queries to 8.8.8.8 are automatically allowed so that domain resolution works. You do not need to add it manually.

IP and CIDR rules

Use IP addresses or CIDR ranges directly when you know the destination IPs.
sbx = Sandbox.create(
    network={
        "deny_out": [ALL_TRAFFIC],
        "allow_out": [
            "1.1.1.1",        # exact IP
            "8.8.8.0/24",     # CIDR range
        ],
    }
)

Combined domains and IPs

Domain and IP rules can be mixed in the same allow_out list.
sbx = Sandbox.create(
    network={
        "allow_out": [
            "*.openai.com",
            "8.8.8.8",           # Google DNS (by IP)
        ],
        "deny_out": [ALL_TRAFFIC],
    }
)

Priority rules

Allow rules always take precedence over deny rules, regardless of order.
The evaluation order is:
  1. If the destination matches any allow_out entry, the connection is permitted.
  2. If the destination matches any deny_out entry, the connection is rejected.
  3. If no rule matches, the connection is permitted by default (unless deny_out=[ALL_TRAFFIC]).

SandboxNetworkOpts model

FieldTypeDescription
allow_outlist[str]Domains, IPs, or CIDRs to allow
deny_outlist[str]Domains, IPs, or CIDRs to deny; use ALL_TRAFFIC to deny everything
mask_request_hoststr | NoneOverride the Host header on outbound requests

Host header masking

Use mask_request_host to override the Host header on all outbound requests. Useful when routing traffic through an internal proxy.
sbx = Sandbox.create(
    network={"mask_request_host": "internal-proxy.company.com"}
)

How enforcement works

Domain and IP rules are enforced at two layers:
  • Layer 3/4 (iptables): IP and CIDR rules are applied as kernel iptables DROP rules. No userspace proxy overhead.
  • Layer 7 (TCP proxy): For domain-based rules, all TCP traffic is redirected to the per-namespace proxy. HTTP Host headers and TLS SNI fields are inspected before forwarding.
UDP and QUIC (HTTP/3) are not supported for domain-level filtering. Domain rules apply only to TCP traffic on ports 80 and 443. Use IP/CIDR rules if you need UDP filtering.

Block cloud metadata service

Cloud instances expose a metadata endpoint at 169.254.169.254. This is automatically blocked in all sandboxes to prevent SSRF attacks.
# This is always blocked, even with no network policy configured
result = sbx.commands.run("curl -s http://169.254.169.254/latest/meta-data/")
print(result.exit_code)  # non-zero (connection refused)

Using SecurityPolicy network configuration

For richer network control integrated with PII scanning and audit logging, use NetworkPolicy inside a SecurityPolicy:
from declaw import Sandbox, SecurityPolicy, NetworkPolicy, ALL_TRAFFIC

policy = SecurityPolicy(
    network=NetworkPolicy(
        allow_out=["*.openai.com", "*.anthropic.com", "pypi.org"],
        deny_out=[ALL_TRAFFIC],
        allow_public_traffic=False,
    ),
    audit=True,
)

sbx = Sandbox.create(security=policy)