Appearance
Networking
Configure runtime network capabilities and proxy routing using structured fields. Settings can be defined globally and overridden per-app or per-launch profile.
What You'll Learn
- How to define network capabilities and proxy catalogs across global, app, and launch profile scopes
- How proxy routing rules are evaluated, prioritized, and merged — and which platform applies what
- Patterns for ZTNA egress, QUIC/DoH controls, and local egress proxy injection
One shape, applied per platform
configuration.network, proxyRouting[] and proxies[] are one shape on Windows and macOS; a document authored for either decodes on both. What each platform enforces differs:
| macOS daemon | Windows client | |
|---|---|---|
capabilities (egress default, inbound/outbound, protocols, ports, DNS) | Enforced per connection | Accepted and ignored |
proxyRouting[].match (hosts, cidrs, ipRanges, ports, protocol) | Evaluated per connection | Accepted and ignored |
proxyRouting[].siteRefs | Accepted and ignored (no site concept) | Selects the rule for the chosen site |
action.type: proxy | Routes the connection via proxyRef | Launches the app with proxyRef as its proxy |
action.type: direct / deny | Connects directly / blocks the connection | Both mean no proxy (deny logs a warning — Windows has no per-connection enforcement) |
action.failover, action.proxyCandidates | Applied | Accepted and ignored |
proxies[].resolveViaProxy | Accepted | Emits --disable-proxy-resolve-via-proxy when false |
A rule may carry match, siteRefs, or both; absent match means every destination and absent siteRefs means every site. Only id and action are required (enabled defaults to true, priority to 500). The Windows template's site-based rules and the macOS daemon's destination-based rules therefore live in one proxyRouting list, each platform applying the part it understands.
Where to configure
- Global (all launches):
configuration.network(NetworkConfig) - Per-app (for that app’s launches):
apps[].modifications.network(NetworkOverrides) - Per-launch profile (only when that launch profile is selected):
apps[].profiles[].network(NetworkOverrides)
Support notes
- Capabilities (macOS daemon)
outboundAllowed,inboundAllowed, ports allow/deny, and TCP/UDP protocol gating are supported by the runtime.dnsAllowed,dnsServers, anddnsSearchSuffixesare supported when the runtime provides DNS control. If not supported by the environment, these are ignored safely.protocols:"tcp"and"udp"are supported."icmp"may be runtime-dependent.egressDefaultActionis enforced by policy evaluation when noproxyRoutingrule matches (ports/protocols still apply).
- Proxies
- Proxy types supported in policy: "http", "https", and "socks5".
- HTTP/HTTPS proxies carry TCP streams. UDP through proxy is runtime-dependent; SOCKS5 may support UDP ASSOCIATE, but verify in your environment. Prefer direct routing for UDP unless validated.
credentialsRefandtls.caBundleRefare opaque references; policy never contains secrets or raw PEM content.useTls: truewraps a SOCKS5 proxy connection in TLS (SOCKS5-over-TLS via stunnel, nginx stream, or similar).tlsSkipVerify: true(ortls.skipVerify: true, the same setting) skips certificate verification; use only on trusted networks with self-signed certs.resolveViaProxy: falsetells the launcher this proxy cannot resolve hostnames — typical for internal SOCKS5 endpoints addressed by raw IP. When every eligible proxy for the selected site hasresolveViaProxy: false, the launcher emits--disable-proxy-resolve-via-proxyand the client performs DNS locally. The launcher emits this flag before the CLI picks a single proxy from the fallback list, so proxies in the same routing group should agree; mixed groups keep the default of DNS-via-proxy.- Site anchors: Site profiles can anchor to proxies via
profiles[].anchor.proxyRef. See Sites.
Network Allow-List
Turbo Server can author a host-level allow-list and deliver it in the policy, so you do not have to write proxyRouting rules by hand. This support is staged for release.
What administrators set (Turbo Server Admin, Workspaces > Policy > Network):
- Default Action: what happens to a connection no rule matches. Deny turns the rules into an allow-list. When it is not set, macOS denies unmatched connections and the Windows sandbox service does not filter, so set it explicitly.
- Daily Reading Allowance for Unlisted Sites: under Deny, how much a sandboxed project may read from sites no rule lists in a day. See Reading unlisted sites.
- Access Rules: each rule names hosts, destination classes, optional ports, and an action: allow (directly or through a proxy), read, or deny. Rules are evaluated from the highest priority down, and the first match decides.
- Destination Classes: named sets of hosts. The built-in classes are updated with server releases: Model APIs, Agent services, Package registries, Container registries, Toolchain downloads, Git hosting, Certificate authorities, Documentation and reference, the denied Paste, file-drop and tunnel services, and Shared hosting. You can add your own.
- Let Project Owners Allow Hosts: off by default. When on, each project's owner can add hosts for that project (see below), and the end-of-run card offers Allow for a blocked site that can be allowed. When off, the card lists what was blocked and offers nothing. The card never says why a site was blocked; the reason is in View Activity.
A host is a name such as docs.example.com, or a wildcard such as *.example.com, which does not match example.com itself. A rule matches a host as a whole. URLs, paths and HTTP methods are refused, because a connection-level control cannot see them; the one exception is a path prefix on an exact host in a read rule, which the inspecting proxy checks. Use Sandboxed Read-Only HTTP or an HTTPS-inspecting enterprise proxy for request-level control.
The server delivers access rules as proxyRouting rules with ids starting access., above your own routing rules. Destination classes are expanded into hosts before the policy is signed.
Read rules. A rule with the action read lets a sandboxed project download from its hosts and send nothing to them. Turbo's inspecting proxy terminates each connection and lets through only a GET or HEAD with no body, a URL of at most 2,048 characters, and a query only of a signed download's fields. It sends upstream a request it builds itself, without cookies or credentials. Anything else is refused and recorded. Shared hosting, such as a cloud storage bucket or a static-site host, can be read only under a path inside one publisher's space, because whoever publishes there can see the requests. Read rules reach clients that declare policy contract 7. An older client receives a read rule as a direct allow when it predates reads, and does not receive a rule that was read only from the start, such as the reference sites below.
What a new server starts with. A new server denies by default and seeds these rules. You can edit, disable or delete each one.
| Rule | Action | Classes | Ports |
|---|---|---|---|
launch-block-exfiltration (priority 900) | Deny | Paste, file-drop and tunnel services | all |
launch-defaults (500) | Allow | Model APIs, Agent services, Package registries, Container registries, Toolchain downloads, Git hosting | 443 |
launch-reference-reads (500) | Read | Documentation and reference | 443 |
launch-certificate-checks (500) | Allow | Certificate authorities | 80, 443 |
launch-git-ssh (500) | Allow | Git hosting | 22 |
Documentation and reference holds the documentation of the major languages, frameworks, databases and cloud platforms, the web standards, and reference and Q&A sites such as MDN, Stack Overflow and Wikipedia. Every host in it is run by one publisher, so only that publisher sees what a project reads. Some registry, toolchain and GitHub download hosts in the allowed classes are read only too.
A new server also sets a daily reading allowance of 16 KB for unlisted sites.
A server that was seeded before a default was added receives that default once, at its next start, as long as it still has launch-defaults. A server whose default action is Deny and that sets no allowance receives the 16 KB allowance the same way. A default rule you delete, or an allowance you clear, is not added again.
Reading unlisted sites
With the default action Deny, a sandboxed project can still read from a site that no rule lists, as long as it has allowance left. Set the allowance on Policy > Network under Daily Reading Allowance for Unlisted Sites, in KB, up to 1,024 KB. Leave it blank or 0 to deny those sites. The policy field is configuration.network.capabilities.unlistedReadAllowanceBytes, in bytes.
- What is allowed. Only reads: a GET or HEAD with no body, over HTTPS or HTTP on ports 443 and 80, to a site named by its host name. Turbo's inspecting proxy checks each request and rebuilds it without cookies or credentials. Sending is refused, as on any read rule. Your deny rules still apply first, so the paste, file-drop and tunnel services stay blocked.
- What is counted. Not the bytes downloaded, and not the bytes sent. A request is charged only for what the app chose freely. A link or address the project received in an earlier download costs a few bits, so following links and search results costs a few bytes a page. A host name, path segment or query value the project never received costs its full length, and each separator between them a few bits. Each connection and each request also costs 2 bytes. Turbo sends a request to an unlisted site with its own fixed headers. Looking up a name the project never received, and no rule lists, is charged the same way, once per name: a name paid at the lookup is not charged again when the project connects. The allowance is per project, across all its sessions, over a rolling 24 hours, and a restart of the Mac does not reset it.
- What it protects. The allowance limits how much a project can carry out of the sandbox through the addresses it reads, for example by hiding a file's contents in made-up URLs. It does not stop a short secret, such as an API key, which fits in one address; keep secrets out of the sandbox.
- When it runs out. Further reads from unlisted sites, and lookups of names the project has not paid for, are refused, and the refusal is recorded in View Activity with its reason. The end-of-run card lists each site as Download blocked, without saying which limit refused it. It offers Allow, which adds the site to the project as a read-only site, only while Let Project Owners Allow Hosts is on. A project's own read-only sites are not charged.
- Certificates. To read unlisted sites, the project's certificate authority is not limited to named sites. It is created on the device, never leaves it, and is trusted only by apps in that project. An app that pins its certificates cannot read unlisted sites.
- Where it applies. macOS clients that declare policy contract 9. An older client receives the policy without the allowance and denies unlisted sites. Windows does not apply it yet. A workspace's Network list turns it off for that workspace's projects.
Per workspace. A workspace's Network tab holds a further restriction for that workspace: its sandboxed projects reach only the hosts on the list, and only those the global rules also allow. Lookups and connections to the project itself (loopback) are not restricted. A disabled list restricts nothing. Applied on macOS.
Per project. When the administrator allows it, a project's owner can list hosts that project may reach beyond the allow-list: in the Portal under Settings > Projects > Network, or in the Mac launcher from the project's menu, Allowed Hosts…. A project's hosts only decide connections that no administrator rule matched, so a deny rule or a proxy route for the same host still applies. At most 32 hosts per project, each a full host name or a wildcard over a named domain (*.example.com, not *.com); addresses and single-label names such as localhost are refused. In a team workspace, only an administrator can change the hosts of the shared Default project.
Where it is enforced
| macOS | Windows | |
|---|---|---|
| Deny rules, with default action Allow | Per connection | Sandbox service refuses the launch; the launcher on its own does not filter |
| Allow rules, with default action Deny | Per connection (see below) | Sandbox service only, through one proxy (see below) |
| Workspace restriction | Sandboxed projects | Not applied |
| Project hosts | Sandboxed projects | Not applied |
A project with sandboxing off has an open network on macOS; its connections are still recorded. Under enterprise-owned inspection, project hosts are not applied: the enterprise proxy decides what is reachable.
How macOS applies an allow-list. With the default action Deny, a managed session reaches the hosts your rules allow and nothing else. It keeps its name lookups and connections to itself (loopback), unless the policy turns DNS off. A connection is checked by the address it goes to, and the Mac admits the addresses of the hosts your rules allow by looking those hosts up itself. Two things follow:
- A host allowed only through a wildcard, such as
*.corp.example, is reachable once the session has looked that host up. An app that resolves names itself instead of asking macOS, as some browsers and developer tools do, cannot reach it. The Network tab points out such rules. - Sites that share an address are told apart by name. An app that resolves names itself, or connects to an address directly, is checked by the name it sends when it opens the connection (the TLS server name or the HTTP host). A connection that names nothing is denied, and so is one whose name does not belong to the address. Connections over UDP (QUIC) are denied under an allow-list, and browsers fall back to TCP.
The Windows sandbox service refuses what it cannot enforce. It does not skip a rule: it refuses to start the sandboxed app. What it can enforce depends on the default action.
- With Deny and any rule that names hosts or ports, denies, or connects directly, the service checks each connection against the rules, and it needs a proxy to do so. The rules must route through exactly one proxy between them, and that proxy must be given by IP address, not by name, and must resolve names itself. Every rule must name hosts, and ports must be single numbers, not ranges. With that in place, rules that allow directly, allow through the proxy, and deny all work. A list of directly allowed hosts with no proxy at all is refused.
- With Allow, or with no default action, the service only sends every connection through one proxy. A deny rule is refused, and so is a rule that sends some hosts through a proxy. Rules that allow hosts directly are accepted and change nothing, since everything is already allowed.
- In either case the service refuses a policy that allows inbound connections, turns DNS off, sets DNS servers or search suffixes, or lists protocols without naming
tcp,udpandicmptogether. It refuses allowed or denied port lists in combination with a proxy.
The Network tab shows a warning when the policy as it stands would be refused, and names the rule or setting responsible. It checks this once there is an access rule or the default action is Deny.
Access rules reach only clients that declare policy contract 3, and project hosts only clients that declare contract 4, which the macOS client does. An older client receives the policy without them, so update clients before turning on Deny: an older macOS client would deny the connections the rules were meant to allow.
Changes reach a device at its next policy refresh, five minutes by default.
Automating it. An administrator, or a service with the api:admin scope, can manage the same rules over the API:
text
GET | POST /api/v1/network/access-rules
GET | PUT | DELETE /api/v1/network/access-rules/{id}
GET | POST /api/v1/network/destination-classes
GET | PUT | DELETE /api/v1/network/destination-classes/{id}json
{ "name": "allow-docs", "hosts": ["docs.example.com", "*.corp.example"], "classes": ["gitRemote"],
"ports": ["443"], "action": "allow", "proxyRef": null, "priority": 500, "enabled": true }A rule's name and a class's key cannot change after creation. The class list includes the built-in classes, which have no id and cannot be changed. Deleting a class that a rule or a workspace list uses is refused.
Seeing what happened. Policy > Network > View Activity lists the destinations devices allowed and denied, the rule that decided, and how many connections. A denied destination has an Allow action that starts a new rule for it. Activity is kept for 30 days by default (Turbo:Network:DecisionRetentionDays). Changes to rules, classes, the default action, a workspace's list and a project's hosts are written to the audit log.
Sandboxed Read-Only HTTP
In builds with inspected-HTTP support, select configuration.network.readOnlyHttp for an API-aware application launched through the sandbox service with policy-defined networking. The service performs approved HTTPS reads and audits decisions and outcomes. The sandbox receives no raw network capabilities and block-all egress filters. This support is staged for release; older services reject the new field, and unsupported XVMs are refused before the inspection endpoint opens.
json
{
"configuration": {
"network": {
"readOnlyHttp": {
"policyId": "docs-read-v1",
"origin": "https://example.com",
"resources": [{ "id": "home", "path": "/" }]
}
}
}
}Use one canonical lowercase HTTPS DNS origin and exact resource paths. Only GET and HEAD are supported. POST, caller headers, request bodies, redirects, cookies and authentication are not supported. Queries are denied unless a resource has a query object mapping each allowed parameter name to a finite list of allowed values, for example "query": { "page": ["1", "2"] }. Optional protectedValues contains literal values to detect in requests; matching is limited and is not a general guarantee against transformed-data exfiltration.
readOnlyHttp must be the only member of configuration.network: do not combine it with capabilities, proxies, proxyRouting, or sandboxScopes, even empty ones. App/profile network overrides are not supported in this mode. An explicit offline launch remains offline and receives no inspection descriptor.
Applications must support the service's descriptor argument contract or integrate the supplied HTTP client helper. This is not transparent browser or curl access. For an explicit Node read tool, stage SandboxHttpClient.exe, its two bootstrap JavaScript files, node.exe and your application together. Launch the helper with original arguments --node node.exe agent.js under this policy. Your script can call await globalThis.turboInspectedRead(url, { signal }) to receive body bytes as a Buffer. It accepts a method and cancellation signal, but no custom headers or request body. Existing fetch, HTTP and Electron APIs are not replaced. The Node bridge passes sandboxed read/denial/audit checks and a LocalSystem test with real WFP filters. Service-host death terminates the agent and closes its endpoint; restart retains filters and audit, and authenticated sandbox destruction removes the filters. A compatible Electron runtime can also run a headless agent with original arguments --electron-node Code.exe agent.js. This explicit mode uses Electron's Node runtime and the same inspected-read API. It passes approved read, audited POST/query denial and direct-TCP refusal checks under LocalSystem with real WFP filters. Normal service stop and abrupt host death terminate the worker and its child; restart retains filters/audit, and authenticated sandbox destruction removes the filters. These tests use an isolated service registration. Full Electron main/utility/extension-host integration remains experimental. Native diagnostics place its pre-application failure in Chromium's alternate window-station initialization; no network or sandbox restrictions were relaxed. A fetch tool running on the server is outside the local descriptor contract and needs its own explicit integration. For a custom Node/Electron agent, agent-web-read.js supplies a callable web_read definition and execute adapter over the inspected API. It accepts a URL and returns bounded UTF-8 text or a fixed error. Register it explicitly in your agent framework; existing vendor CLI web tools are not replaced. Enterprise mode requires a supplied enterprise-proxy transport and never falls back to Turbo inspection or direct fetch. For a native tool client, the helper also exposes web_read over stdio MCP. An inspected launch using --claude-mcp claude.exe <args> supplies per-launch MCP configuration to a staged native Claude executable. Native Claude tool discovery and sandboxed MCP reads have passed separate observing-filter tests; native Claude tool execution remains separate. The persistent MCP helper also passes LocalSystem tests with real WFP filters: service stop and crash terminate the helper and client, close the endpoint, and preserve audit across restart. Authenticated sandbox destruction removes the retained filters. These tests use isolated service registrations and do not establish native-Claude lifecycle or enterprise deployment acceptance. Native Codex now passes native app-server tool invocation for approved reads, query denial, invalid write arguments and redacted broker audit, without a model request. An AppContainer path-resolution compatibility fix verifies the same file through an existing accessible drive mapping; device access stays denied. The initial native fixture observes filter installation. Separate LocalSystem tests now validate native Codex reads and denials with real WFP and direct TCP refusal. Service stop or crash terminates the observed Codex/MCP-helper tree and closes the endpoint; audit and filters survive restart until authenticated sandbox destruction removes filters. Native Claude lifecycle and enterprise deployment acceptance remain pending. This does not enable model-provider traffic or replace the vendor's built-in web tools. Enterprise-proxy deployments use their own selected transport and do not load the Turbo inspection endpoint.
For enterprise-owned inspection, set global configuration.network.inspectionAuthority to "enterprise-proxy" with outbound access, egressDefaultAction: "deny", and universal proxy routing. The Windows service requires literal proxy endpoint pinning and proxy-side DNS, and refuses direct routes, bypasses, local readOnlyHttp or local sandbox CASB scopes. This selection starts no Turbo inspection endpoint. A successful proxy tunnel does not attest content inspection; validate the enterprise's authentication, TLS inspection and audit integration before deployment. Policy/schema checks and launch-to-filter delivery tests pass. A separate LocalSystem test with real WFP also verifies proxied HTTP access, refusal with a wrong fixture credential, and direct IPv4 TCP denial without either Turbo broker endpoint. This does not require inference from a timeout: the test requires Windows AccessDenied. The current-source rerun passes with zero skips. This does not validate enterprise TLS inspection, read-only request enforcement or request-audit correlation; enterprise-product acceptance remains pending.
Supply both url and a brief purpose when calling MCP web_read. Purpose is required, limited to 256 characters, and must not contain control characters, credentials or sensitive content. The broker records it as an untrusted claim; it cannot override resource, query or method restrictions. The broker removes purpose before constructing the outbound request. Audit text is escaped and explanations containing configured protected values are redacted; this does not detect every possible secret. Older non-MCP clients may omit purpose.
MCP requests run serially; cancellation waits for the active read's existing deadline. Invalid MCP arguments are rejected locally and do not create broker network-audit records. Reads are restricted to approved resources; GET semantics alone do not guarantee that a remote endpoint has no side effects. The client bounds a request to 30 seconds and closes stalled connections; transport loss is not a successful read. Audit records omit raw URLs, query values and response bodies. They do not provide request-level records for OS-blocked socket attempts.
The service-policy launch path has passed LocalSystem acceptance with a distinct interactive caller and two real WFP filters. The test verifies an approved public read, audited POST and query denials, and blocked direct TCP access. The fixture explicitly removes its filters after testing.
A separate LocalSystem test verifies that manager shutdown terminates the XVM root, application and child, and closes the HTTP endpoint. Recreating the manager retains the audit records and filters without reviving the endpoint. Filters remain until you destroy the sandbox; the production destruction path removes them and audits cleanup.
Abrupt host death also passes LocalSystem testing with real filters: killing the disposable service host terminates the agent tree and closes the HTTP endpoint. Restart retains filters and audit records; sandbox destruction removes and audits the filters.
Isolated SCM tests also pass normal service stop and abrupt host death followed by restart. They run the production service as LocalSystem and use a real user process on the authenticated control endpoint for launch and destruction. The tests use a temporary service registration and fixture policy; they do not verify enterprise installation upgrades or automatic SCM recovery actions.
Sandboxed Host Rules
Host rules authorize destinations, not HTTPS request content or individual API operations. Use read-only HTTP mediation above or an HTTPS-inspecting enterprise proxy when request-level controls are required. A pass-through CONNECT tunnel cannot enforce HTTP methods.
Enterprise proxy servers can own content inspection and destination filtering. The existing universal proxy-only policy path enforces the configured proxy route without requiring Turbo's local host-rule classifier or content detectors. Local host restrictions are an additional control when you choose to use them. Successful proxy connectivity does not establish that TLS inspection or DLP occurred; validate those controls on the enterprise proxy. Retain enforced proxy routing and avoid direct or bypass routes when the enterprise proxy must inspect all application traffic.
In a broker-capable Sandboxed service build, use an explicit egressDefaultAction: "deny" with host-specific proxyRouting rules to enforce CONNECT host and port decisions. This support is staged for release; older service builds refuse these constructs. The broker evaluates enabled rules by descending priority, then ordinal id. An unmatched connection is denied. Use action.type: "deny" for an explicit denial and action.type: "proxy" to allow a destination through one referenced upstream.
Use exact or glob host patterns, optional protocol: "tcp", and optional single port numbers in match.ports. The upstream must use resolveViaProxy: true and a remote literal address. CIDRs, IP ranges, site references, capability port restrictions, custom trust bundles and unresolved credential references remain unsupported on this path and refuse the launch. These rules govern CONNECT destinations, not HTTPS paths or content.
Use action.type: "direct" to open an allowed TCP destination from the service without the upstream proxy. A proxy's bypassHosts selects that same direct path only after the global and scoped rules allow the request. Exact and glob patterns retain their meaning; bypass never overrides a denial or grants an unmatched destination. This staged form still requires one referenced upstream and an explicit global default denial.
The payload continues to use the authenticated relay for direct routes. The service resolves a direct hostname after authorization and checks every address before connecting to a checked literal. Loopback, private, shared, link-local, multicast, unspecified, host-interface, 6to4 and Teredo addresses are refused. DNS resolution for an allowed direct hostname is expected; a proxy failure never falls back to a direct connection.
To further restrict one sandbox, add configuration.network.sandboxScopes:
json
"sandboxScopes": [
{
"ownerSid": "S-1-5-21-100-200-300-1001",
"isolationContextId": "restricted-work",
"hosts": [{ "pattern": "approved.example", "patternType": "exact" }],
"ports": [443]
}
]Add this fragment beside global capabilities, proxies, and proxyRouting. Replace the example SID with the sandbox owner's Windows SID. Context names are case-sensitive. A request must satisfy both the global rule and the scoped host/port restriction. A missing scoped entry uses the global policy; malformed entries and duplicate owner/context pairs refuse policy loading. Choosing a different sandbox name can never grant more access than the global policy.
The service keeps proxy credentials outside the payload, authenticates the relay client's package SID, and blocks direct payload egress using WFP. Live IPv4 forwarding and denial have been validated. A controlled-resolver test observed no query for a denied real-XVM hostname, with successful hookless DNS controls before and after it. IPv6 SOCKS framing and upstream sockets pass local tests; off-host IPv6 forwarding and WFP validation remain pending for this staged support.
As of September 6, 2026, that live IPv6 validation is blocked because the test environment has no usable global IPv6 interface or IPv6 proxy endpoint. Local IPv6 results do not establish off-host enforcement. Validation must resume on an IPv6-capable network with a reachable IPv6 proxy, successful connectivity controls before and after WFP enforcement, and both allowed and denied broker requests under enforcement.
The relay uses asynchronous pipe I/O with bounded connection capacity; idle connections do not reserve service worker threads. Host-policy audit records describe authorization decisions. An allow record does not confirm a successful upstream connection or completed transfer.
Field reference
Global (NetworkConfig)
json
{
"configuration": {
"network": {
"capabilities": {
"outboundAllowed": true,
"inboundAllowed": false,
"dnsAllowed": true,
"protocols": ["tcp", "udp"],
"ports": { "allow": ["80", "443", "10000-10100"], "deny": ["25"] },
"dnsServers": ["1.1.1.1", "2606:4700:4700::1111"],
"dnsSearchSuffixes": ["corp.local"],
"egressDefaultAction": "deny"
},
"proxies": [
{
"id": "corp-proxy",
"type": "https",
"url": "https://proxy.corp.local:8443",
"credentialsRef": "corp-proxy-service-acct",
"bypassHosts": [ { "pattern": "*.corp.local", "patternType": "glob" } ],
"connectTimeoutMs": 5000,
"tls": { "verify": true, "caBundleRef": "corp-root-bundle" }
},
{
"id": "socks-exit",
"type": "socks5",
"url": "socks5://socks-gw.corp.local:1080",
"credentialsRef": "socks-user",
"useTls": true
},
{
"id": "socks-internal-ip",
"type": "socks5",
"url": "socks5://10.0.0.20:1080",
"credentialsRef": "socks-user",
"resolveViaProxy": false
}
],
"proxyRouting": [
{
"id": "rfc1918-direct",
"enabled": true,
"priority": 900,
"match": { "cidrs": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] },
"action": { "type": "direct" }
},
{
"id": "cdn-direct",
"enabled": true,
"priority": 850,
"match": {
"hosts": [ { "pattern": "*.cdn.example.com", "patternType": "glob" } ],
"ports": ["443"],
"protocol": "tcp"
},
"action": { "type": "direct" }
},
{
"id": "internet-via-proxy",
"enabled": true,
"priority": 800,
"match": { "hosts": [ { "pattern": "*", "patternType": "glob" } ], "protocol": "tcp" },
"action": { "type": "proxy", "proxyRef": "corp-proxy", "failover": "deny" }
},
{
"id": "site-us-proxy",
"siteRefs": ["san-jose"],
"action": { "type": "proxy", "proxyRef": "corp-proxy" }
}
]
}
}
}The last rule has no match: it is a site-based selection the Windows client applies for every launch at the san-jose site, and a catch-all the macOS daemon applies to every destination not claimed by a higher-priority rule.
Per-app overrides (NetworkOverrides)
json
{
"id": "sensitive-editor",
"displayName": "Sensitive Editor",
"enabled": true,
"priority": 300,
"matchAll": [
{ "type": "targetPath", "pattern": "**\\\\SensitiveEditor.exe", "patternType": "glob" }
],
"action": "allow",
"modifications": {
"network": {
"capabilities": { "egressDefaultAction": "deny" },
"proxyRouting": [
{
"id": "vendor-api-direct",
"enabled": true,
"priority": 950,
"match": {
"hosts": [ { "pattern": "api.vendor.example", "patternType": "exact" } ],
"ports": ["443"],
"protocol": "tcp"
},
"action": { "type": "direct" }
}
]
}
}
}Per-launch profile overrides (NetworkOverrides)
json
{
"id": "diagnostic-mode",
"displayName": "Run (Diagnostic)",
"network": {
"capabilities": { "egressDefaultAction": "allow" }
}
}Credentials and secret storage
- Do not embed secrets in policy. Use proxies[].credentialsRef to reference credentials stored by the client or enterprise tooling. The value is an opaque key resolved at runtime. See Variable Substitution for how to use these references securely.
- For HTTPS proxies, enable certificate verification (tls.verify: true) and pin trust using tls.caBundleRef when required. See Security Best Practices.
- Proxy performance data and user selections are maintained outside policy (see Proxy Settings); proxies.json persists latency measurements and selection but does not contain secrets.
Destination matching
- hosts: Array of HostPatternSpec objects with pattern and patternType (glob recommended, e.g., "*.corp.local"). Case-insensitive.
- cidrs: Array of IPv4/IPv6 CIDRs (e.g., "10.0.0.0/8", "2001:db8::/32").
- ipRanges: Explicit from/to IP ranges.
- ports: Array of PortSpec strings (single "443" or range "10000-10100").
- protocol: "tcp" | "udp" | "icmp" (runtime support for icmp may vary).
Evaluation and precedence (macOS daemon, per connection)
- Merge scopes: Global → App (Policy) → Launch Profile. For capabilities, booleans last-wins, arrays last-wins replacement, and the ports object replaces as a whole across scopes. Within a scope, ports.deny overrides ports.allow.
- Choose a routing rule: Collect enabled rules from all scopes. For a connection, evaluate rules whose
matchpasses (a rule withoutmatchpasses for every destination); select highest priority (descending), then rule id alphabetical. Apply its action: proxy, direct, or deny.- Deny short-circuits (connection is blocked).
- If action = proxy and the proxy endpoint is unreachable, the connection fails unless the rule states a
failover(directordeny). The default is deliberate: silently falling back to a direct connection would send traffic around the proxy the policy selected at exactly the moment the proxy stopped working.proxyCandidatesnames the only alternates the daemon's proxy health may substitute forproxyRef. Deploy proxy redundancy behind the name the rule points at (a load-balanced VIP, or a hostname with several addresses) rather than relying on failover.
- Apply posture controls: Regardless of routing outcome, enforce outboundAllowed/inboundAllowed, protocol, and port constraints. If no rule matched, fall back to egressDefaultAction along with protocols/ports.
Evaluation (Windows client, per launch)
- Filter enabled rules to those whose
siteRefsinclude the selected site or are absent. - Take the highest-priority rule (then id). If its action is
proxy, the launch usesproxyRef;directordenymeans the launch has no proxy. capabilitiesandmatchare accepted and ignored; Windows has no per-connection enforcement today.
Local egress proxy pattern (header/tag injection)
- To add headers or tags (e.g., an App-ID for a downstream device), route matching traffic to a local proxy that performs the injection, then forwards to the destination.
- Define a loopback proxy and a routing rule targeting it:
json
{
"proxies": [
{ "id": "local-egress", "type": "http", "url": "http://127.0.0.1:8080" }
],
"proxyRouting": [
{
"id": "tag-sensitive-traffic",
"enabled": true,
"priority": 925,
"match": { "hosts": [ { "pattern": "*.sensitive.example", "patternType": "glob" } ], "ports": ["443"], "protocol": "tcp" },
"action": { "type": "proxy", "proxyRef": "local-egress" }
}
]
}- The local proxy can inject headers (for example, X-App-Id) or adjust SNI before forwarding to the enterprise proxy or direct internet, according to your security tooling (e.g., Palo Alto Networks).
Identity-aware networking and ZTNA integration
- ZTNA agents or sidecars are typically exposed as local or near-edge proxies (for example,
https://127.0.0.1:8443or a gateway host). - Model these components as entries in
configuration.network.proxiesand pin application egress to them usingproxyRoutingrules andNetworkOverrides. - Session-level and identity-centric decisions (user identity, device posture, and risk signals) are made by the ZTNA platform; the Launcher enforces which flows must traverse the ZTNA path and which are denied or allowed directly.
- For sensitive applications, combine per-app
network.capabilities.egressDefaultAction: "deny"with narrow allow rules so that any traffic not explicitly routed to the ZTNA proxy is blocked.
Example (ZTNA agent as local egress)
json
{
"configuration": {
"network": {
"proxies": [
{
"id": "ztna-agent",
"type": "https",
"url": "https://127.0.0.1:8443"
}
],
"proxyRouting": [
{
"id": "internal-direct",
"enabled": true,
"priority": 900,
"match": {
"cidrs": ["10.0.0.0/8", "172.16.0.0/12"]
},
"action": { "type": "direct" }
},
{
"id": "sensitive-app-via-ztna",
"enabled": true,
"priority": 800,
"match": {
"hosts": [
{ "pattern": "*.corpapps.example", "patternType": "glob" }
],
"protocol": "tcp"
},
"action": { "type": "proxy", "proxyRef": "ztna-agent" }
}
]
}
},
"apps": [
{
"id": "sensitive-editor",
"modifications": {
"network": {
"capabilities": {
"egressDefaultAction": "deny"
}
}
}
}
]
}Notes
- Per-app and per-profile overrides allow you to require ZTNA for specific applications while leaving less sensitive apps on standard enterprise proxy paths.
- Use identity-aware routing together with ABAC and Identity Access policy to align SSO and network enforcement.
Modern protocols: QUIC and secure DNS (DoH/DoT)
- QUIC and HTTP/3 are UDP-based protocols (typically using port 443). They are governed by
capabilities.protocolsand the allowed port ranges incapabilities.ports. - To disable QUIC for all applications while keeping HTTPS over TCP, configure
protocolsto include only"tcp". This prevents all UDP traffic, including QUIC, from leaving the runtime.
Example (disable UDP/QUIC, allow HTTPS)
json
{
"configuration": {
"network": {
"capabilities": {
"outboundAllowed": true,
"protocols": ["tcp"],
"ports": {
"allow": ["80", "443"],
"deny": ["25"]
},
"egressDefaultAction": "deny"
}
}
}
}Secure DNS behavior
dnsAllowed,dnsServers, anddnsSearchSuffixescontrol classic DNS flows (typically UDP/TCP 53) when the runtime has DNS control.- DNS over HTTPS (DoH) and DNS over TLS (DoT) are carried as normal TLS/HTTPS traffic to resolver endpoints and are therefore governed by
proxyRoutinghost/port/protocol matching andcapabilities.
Common patterns
- Enforce enterprise DNS or DoH:
- Disable direct DNS where required (
dnsAllowed: falseand/or deny port53). - Allow HTTPS egress only to enterprise resolver endpoints (for example,
dns.corp.local) either directly or through an enterprise proxy.
- Disable direct DNS where required (
- Block consumer DoH/DoT resolvers:
- Add
proxyRoutingrules that match known consumer DNS endpoints by host and setaction.type = "deny".
- Add
Example (enterprise DoH gateway with consumer DoH blocked)
json
{
"configuration": {
"network": {
"capabilities": {
"dnsAllowed": false,
"protocols": ["tcp"],
"ports": {
"allow": ["443"],
"deny": ["53"]
},
"egressDefaultAction": "deny"
},
"proxyRouting": [
{
"id": "block-consumer-doh",
"enabled": true,
"priority": 950,
"match": {
"hosts": [
{ "pattern": "*.dns.google", "patternType": "glob" },
{ "pattern": "mozilla.cloudflare-dns.com", "patternType": "exact" }
]
},
"action": { "type": "deny" }
},
{
"id": "enterprise-doh",
"enabled": true,
"priority": 900,
"match": {
"hosts": [
{ "pattern": "dns.corp.local", "patternType": "exact" }
],
"ports": ["443"],
"protocol": "tcp"
},
"action": { "type": "proxy", "proxyRef": "corp-proxy" }
}
]
}
}
}Notes
- There is no special DoH/DoT object in the schema; DNS resolver control is expressed via
capabilities(protocols/ports/DNS settings) andproxyRoutinghost/port rules. - When QUIC is disabled via
protocols, HTTP/3 falls back to HTTP/2 or HTTP/1.1 over TCP, so proxy and inspection behavior remains deterministic.
Forward compatibility
- To support future vendor-specific options without breaking existing policies, the schema may introduce opaque extension bags on proxies and routing actions (e.g.,
proxies[].extensionsandproxyRouting[].action.extensions). Until then, prefer the local egress proxy pattern above for per-flow tagging.
Semantics and precedence (summary)
- Scope precedence: Launch Profile > Policy (App) > Global.
- Capabilities:
- Booleans last-wins by scope (e.g.,
outboundAllowed,inboundAllowed,dnsAllowed). - Arrays (
protocols,dnsServers,dnsSearchSuffixes) last-wins by scope (replacement). ports.allow/ports.deny: within a scope, deny overrides allow at evaluation time; across scopes, last-wins replacement of the entireportsobject.egressDefaultAction: last-wins by scope.
- Booleans last-wins by scope (e.g.,
- Proxy catalog (proxies[]): defined globally only at
configuration.network.proxies. App/profile scopes reference proxies viaproxyRefand cannot define new proxies. - Proxy routing rules:
- Rules are additive across scopes.
- For a connection (macOS): evaluate enabled rules whose match passes; choose the rule with highest priority (descending), then rule id alphabetical. Apply its action (proxy/direct/deny). Deny short-circuits. If action = proxy and the proxy endpoint is unreachable, the connection fails unless
failoversays otherwise. - Per launch (Windows): the highest-priority rule for the selected site picks the proxy; direct/deny mean no proxy.
Cross-references
- Schema Reference → NetworkConfig, NetworkOverrides, Proxy, ProxyRoutingRule, NetworkCapabilities
- Security Best Practices → Network hardening,
credentialsRef,tls.caBundleRef, QUIC/DoH/DoT patterns - Troubleshooting → Proxy testing and
proxies.json - Variable Substitution → Variable Substitution
