Documentation Index
Fetch the complete documentation index at: https://docs.microsandbox.dev/llms.txt
Use this file to discover all available pages before exploring further.
See Networking for conceptual overview and TLS Interception for TLS proxy details.
Network
Frozen dataclass for sandbox network configuration. Use a class-method preset for the common cases, or construct directly with custom options.
Network(
policy: str | NetworkPolicy | None = None,
ports: Mapping[int, int] | Sequence[PortBinding] = {},
deny_domains: tuple[str, ...] = (),
deny_domain_suffixes: tuple[str, ...] = (),
dns: DnsConfig | None = None,
tls: TlsConfig | None = None,
ipv4_pool: str | None = None,
ipv6_pool: str | None = None,
max_connections: int | None = None,
on_secret_violation: ViolationAction | ViolationPolicy = ViolationAction.BLOCK_AND_LOG,
trust_host_cas: bool | None = None,
)
| Field | Type | Description |
|---|
| policy | str | NetworkPolicy | None | Preset name ("none", "public_only", "allow_all") or custom NetworkPolicy |
| ports | Mapping[int, int] | Sequence[PortBinding] | Port mappings from host to guest. Mapping form binds to 127.0.0.1; PortBinding can set an explicit bind address |
| deny_domains | tuple[str, ...] | Deny egress to these exact domains. Each entry adds a deny Domain("...") policy rule that fires at DNS resolution (REFUSED), TLS first-flight (SNI), and TCP egress (cache fallback). Prepended onto the policy so it takes precedence over later allow rules |
| deny_domain_suffixes | tuple[str, ...] | Deny egress to all subdomains of these suffixes. Adds deny DomainSuffix("...") rules; same enforcement layers as deny_domains |
| dns | DnsConfig | None | DNS interception configuration |
| tls | TlsConfig | None | TLS interception configuration |
| ipv4_pool | str | None | IPv4 pool used for per-sandbox /30 guest subnets. Defaults to 172.16.0.0/12 |
| ipv6_pool | str | None | IPv6 pool used for per-sandbox /64 guest prefixes. Defaults to fd42:6d73:62::/48 |
| max_connections | int | None | Maximum concurrent connections |
| on_secret_violation | ViolationAction | ViolationPolicy | Sandbox-wide action when a secret placeholder reaches a disallowed host |
| trust_host_cas | bool | None | Ship the host’s trusted root CAs into the guest at boot so outbound TLS works behind corporate MITM proxies (Cloudflare Warp Zero Trust, Zscaler, Netskope, etc.). These proxies install a gateway CA on the host that’s unknown to the guest’s stock Mozilla bundle. Opt-in |
Network.allow_all()
@classmethod
def allow_all() -> Network
Unrestricted network access, including to private addresses and the host machine.
Returns
| Type | Description |
|---|
Network | Unrestricted network configuration |
Network.none()
@classmethod
def none() -> Network
Deny all traffic. No network interface is created; the guest is fully offline. exec and fs still work since they use the host-guest channel, not the network.
Returns
| Type | Description |
|---|
Network | Fully airgapped network configuration |
Network.public_only()
@classmethod
def public_only() -> Network
Block private address ranges and cloud metadata endpoints. Allow everything else. This is the default policy.
Returns
| Type | Description |
|---|
Network | Public-only network configuration |
PortBinding
Frozen dataclass for published ports that need an explicit host bind address or UDP.
PortBinding(
host_port: int,
guest_port: int,
bind: str = "127.0.0.1",
protocol: PortProtocol = PortProtocol.TCP,
)
Prefer the protocol-specific constructors:
PortBinding.tcp(8001, 8001, bind="0.0.0.0")
PortBinding.udp(5353, 5353, bind="0.0.0.0")
| Field | Type | Description |
|---|
| host_port | int | Port on the host |
| guest_port | int | Port inside the sandbox |
| bind | str | Host address to bind. Defaults to 127.0.0.1; use 0.0.0.0 for all IPv4 interfaces |
| protocol | PortProtocol | Published port protocol |
PortBinding.tcp() maps to the Rust port_bind(...) path; PortBinding.udp() maps to port_udp_bind(...).
NetworkPolicy
A list of rules plus two per-direction defaults, evaluated first-match-wins. Pass to Network(policy=...) for custom policies:
from microsandbox import (
Action,
DestGroup,
Destination,
Direction,
NetworkPolicy,
Protocol,
Rule,
)
policy = NetworkPolicy(
default_egress=Action.DENY,
default_ingress=Action.ALLOW,
rules=(
Rule.allow(
protocol=Protocol.TCP,
port=443,
destination=Destination.ip("1.1.1.1"),
),
Rule.allow(destination=Destination.group(DestGroup.LINK_LOCAL)),
Rule.deny(destination=Destination.domain("api.example.com")),
),
)
The default policy denies egress except for an implicit allow public, and allows ingress with no rules. See the defaults rationale for the asymmetry.
NetworkPolicy(
default_egress: Action = Action.DENY,
default_ingress: Action = Action.ALLOW,
rules: tuple[Rule, ...] = (),
)
| Field | Type | Description |
|---|
| default_egress | Action | Action when no egress-applicable rule matches |
| default_ingress | Action | Action when no ingress-applicable rule matches |
| rules | tuple[Rule, ...] | Rules evaluated first-match-wins per direction |
Rule order matters
The first matching rule wins, so a broad rule placed before a narrow one swallows it:
policy = NetworkPolicy(
default_egress=Action.DENY,
default_ingress=Action.ALLOW,
rules=(
Rule.allow(destination="10.0.0.0/8"), # matches everything in 10.x
Rule.deny(destination="10.0.0.5"), # never reached
),
)
Put specific rules before general ones.
Rule
Frozen dataclass for a single network policy rule.
Rule(
action: Action,
direction: Direction = Direction.EGRESS,
destination: str | NetworkDestination | None = None,
protocol: Protocol | None = None,
port: int | str | None = None,
)
| Field | Type | Description |
|---|
| action | Action | What to do when this rule matches |
| direction | Direction | Which evaluator considers this rule. Direction.ANY matches in either direction |
| destination | str | NetworkDestination | None | Target filter. Prefer typed Destination helpers for new code. String shorthand remains supported: DestGroup values, exact IPs, domains, CIDR ranges, domain suffixes prefixed with ".", or "*" for any. Domain and suffix strings are validated at sandbox creation; invalid names raise ValueError |
| protocol | Protocol | None | Protocol filter |
| port | int | str | None | Single port (443) or range ("8000-9000") |
Ingress rules carrying ICMP protocols are rejected at sandbox creation; the host has no inbound ICMP path. Use Direction.EGRESS for ICMP allow/deny.
Rule.allow()
@classmethod
def allow(
*,
direction: Direction = Direction.EGRESS,
protocol: Protocol | None = None,
port: int | str | None = None,
destination: str | NetworkDestination | None = None,
) -> Rule
Create a rule that permits matching traffic.
Parameters
| Name | Type | Description |
|---|
| direction | Direction | Traffic direction |
| protocol | Protocol | None | Protocol filter |
| port | int | str | None | Port or port range |
| destination | str | NetworkDestination | None | Destination filter |
Returns
| Type | Description |
|---|
Rule | An allow rule |
Rule.deny()
@classmethod
def deny(
*,
direction: Direction = Direction.EGRESS,
protocol: Protocol | None = None,
port: int | str | None = None,
destination: str | NetworkDestination | None = None,
) -> Rule
Create a rule that blocks matching traffic.
Parameters
| Name | Type | Description |
|---|
| direction | Direction | Traffic direction |
| protocol | Protocol | None | Protocol filter |
| port | int | str | None | Port or port range |
| destination | str | NetworkDestination | None | Destination filter |
Returns
| Type | Description |
|---|
Rule | A deny rule |
Rule.allow_dns()
@classmethod
def allow_dns() -> tuple[Rule, Rule]
Allow plain DNS (UDP/53 and TCP/53) to the sandbox gateway, i.e. the in-process DNS forwarder. The standard one-liner for opening DNS under a deny-by-default policy. See DNS as egress for the underlying semantics.
Returns the pair (udp_rule, tcp_rule) since this SDK’s Rule shape carries a single protocol; splat into NetworkPolicy.rules:
policy = NetworkPolicy(
default_egress=Action.DENY,
rules=(
*Rule.allow_dns(),
Rule.allow(
protocol=Protocol.TCP,
port=443,
destination=Destination.group(DestGroup.PUBLIC),
),
),
)
DoT (TCP/853) is intentionally not included; add an explicit Rule.allow(destination=Destination.group(DestGroup.HOST), protocol=Protocol.TCP, port=853) if needed (and pair with TLS interception).
Returns
| Type | Description |
|---|
tuple[Rule, Rule] | (udp_rule, tcp_rule) for Group::Host on port 53 |
Destination
Factory namespace for typed network policy destinations. Typed destinations avoid string-shorthand ambiguity and match the TypeScript SDK shape.
from microsandbox import DestGroup, Destination
Destination.any()
Destination.ip("1.1.1.1")
Destination.cidr("10.0.0.0/8")
Destination.domain("api.example.com")
Destination.domain_suffix(".example.com")
Destination.group(DestGroup.LINK_LOCAL)
| Method | Returns | Description |
|---|
Destination.any() | NetworkDestination | Match any destination |
Destination.ip(ip) | NetworkDestination | Match an exact IPv4 or IPv6 address. Stored as /32 for IPv4 or /128 for IPv6 |
Destination.cidr(cidr) | NetworkDestination | Match a CIDR range |
Destination.domain(domain) | NetworkDestination | Match an exact domain |
Destination.domain_suffix(suffix) | NetworkDestination | Match the apex domain and all subdomains |
Destination.group(group) | NetworkDestination | Match a DestGroup value |
Bare IP strings such as "1.1.1.1" remain supported and are parsed like Destination.ip("1.1.1.1"). Prefer Destination.ip(...) when the value is known to be an IP address.
NetworkDestination
Frozen dataclass produced by Destination helpers.
NetworkDestination(
kind: Literal["any", "ip", "cidr", "domain", "domain_suffix", "group"],
value: str | None = None,
)
| Field | Type | Description |
|---|
| kind | Literal["any", "ip", "cidr", "domain", "domain_suffix", "group"] | Destination variant |
| value | str | None | Variant value, omitted for Destination.any() |
DnsConfig
Frozen dataclass for DNS interception settings.
DnsConfig(
rebind_protection: bool = True,
nameservers: tuple[str, ...] = (),
query_timeout_ms: int | None = None,
)
| Field | Type | Description |
|---|
| nameservers | tuple[str, ...] | Nameservers (IP, IP:PORT, HOST, or HOST:PORT). Overrides the host’s /etc/resolv.conf when set. Hostnames are resolved once at startup via the host’s OS resolver |
| query_timeout_ms | int | None | Per-DNS-query timeout in milliseconds |
| rebind_protection | bool | Block DNS responses resolving to private IPs |
TlsConfig
Frozen dataclass for TLS interception settings within Network.
TlsConfig(
bypass: tuple[str, ...] = (),
verify_upstream: bool = True,
intercepted_ports: tuple[int, ...] = (443,),
block_quic: bool = False,
ca_cert: str | None = None,
ca_key: str | None = None,
ca_cn: str | None = None,
)
| Field | Type | Description |
|---|
| block_quic | bool | Block QUIC/HTTP3 (UDP) on intercepted ports, forcing TCP/TLS fallback |
| bypass | tuple[str, ...] | Domains to skip interception. Use for domains with certificate pinning |
| ca_cert | str | None | Path to a custom interception CA certificate PEM file |
| ca_cn | str | None | Common name for the generated interception CA |
| ca_key | str | None | Path to a custom interception CA private key PEM file |
| intercepted_ports | tuple[int, ...] | TCP ports where TLS interception is active |
| verify_upstream | bool | Verify upstream server certificates. Set to False only for self-signed servers |
Types
Action
String enum (StrEnum) for policy actions.
| Value | Description |
|---|
"allow" | Permit the traffic |
"deny" | Drop the traffic silently |
Direction
String enum for traffic direction.
| Value | Description |
|---|
"egress" | Traffic leaving the sandbox |
"ingress" | Traffic entering the sandbox (via published ports) |
"any" | Rule applies in either direction |
Protocol
String enum for network protocols in policy rules.
| Value | Description |
|---|
"tcp" | TCP traffic |
"udp" | UDP traffic |
"icmpv4" | ICMPv4 traffic |
"icmpv6" | ICMPv6 traffic |
PortProtocol
String enum for port-level protocol selection.
| Value | Description |
|---|
"tcp" | TCP port |
"udp" | UDP port |
DestGroup
String enum for well-known destination groups used in Destination.group() or string-shorthand Rule.destination.
| Value | Description |
|---|
"public" | Complement of the named categories: every address not in any other group |
"private" | Private/RFC 1918 addresses + ULA + CGN (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 100.64.0.0/10, fc00::/7) |
"loopback" | Loopback addresses (127.0.0.0/8, ::1); the guest’s own loopback, not the host. See the loopback-vs-host watch-out |
"link-local" | Link-local addresses (169.254.0.0/16, fe80::/10) excluding metadata |
"metadata" | Cloud metadata endpoints (169.254.169.254) |
"multicast" | Multicast addresses (224.0.0.0/4, ff00::/8) |
"host" | The host machine, reached via host.microsandbox.internal. This is the right group for “let the sandbox reach my host’s localhost”, not "loopback" |