Network Isolation¶
Every outbound HTTP and HTTPS request from a sandbox is checked against your network policies before it leaves. Policies are written in the same simple policy DSL used for RBAC — giving you fine-grained control over which external services a sandbox can reach.
This is a core part of Tilde's security model: autonomous agents and automated pipelines should only access the network resources they need, nothing more.
Why Network Policies Matter¶
When you give an AI agent access to your data and let it run code, it can do anything a program can do — including making HTTP requests. Without network controls, a sandbox could:
- Exfiltrate data to unauthorized external services
- Call arbitrary APIs using credentials found in the environment
- Reach cloud metadata endpoints (like
169.254.169.254) to escalate privileges - Access internal services on private networks that should be off-limits
- Download and execute untrusted code from the internet
Network policies prevent all of this. Every outbound request is evaluated against your organization's policies before it is allowed to proceed.
How It Works¶
Every outbound HTTP and HTTPS request from a sandbox is evaluated before it leaves:
- Baseline rules unconditionally block requests to dangerous destinations (private networks, cloud metadata, loopback). These cannot be overridden by policy.
- Network policies check the request against your organization's allow/deny rules.
- Allowed requests proceed to the upstream server. Denied requests return
403 Forbiddento the sandbox.
There is no way for code inside a sandbox to opt out — the only path off the sandbox network is through this enforcement layer.
Baseline Protection¶
Before any policy is evaluated, requests to dangerous network destinations are unconditionally blocked. These rules are always enforced and cannot be overridden by policies:
| Range | Purpose |
|---|---|
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 |
Private networks (RFC 1918) |
169.254.0.0/16 |
Link-local addresses, including cloud metadata endpoints (AWS, GCP) |
100.64.0.0/10 |
Carrier-grade NAT (shared address space) |
127.0.0.0/8 |
Loopback |
198.18.0.0/15 |
Benchmark/testing range |
| IPv6 equivalents | ::1, fe80::/10, fd00::/8 |
DNS is resolved and the resolved IP addresses are checked against these ranges before any connection is established. This prevents DNS rebinding attacks where a hostname initially resolves to a public IP but later resolves to a private one.
Default Policy¶
Every organization gets a built-in DefaultNetworkAccess policy that provides a sensible starting point. It allows access to common package managers, AI APIs, and code hosting services while denying everything else:
# Language package managers
HttpRequest(host:"registry.npmjs.org")
HttpRequest(host:"registry.yarnpkg.com")
HttpRequest(host:"pypi.org")
HttpRequest(host:"files.pythonhosted.org")
HttpRequest(host:"*.crates.io")
HttpRequest(host:"rubygems.org")
HttpRequest(host:"proxy.golang.org")
HttpRequest(host:"sum.golang.org")
# OS package managers — Debian / Ubuntu (apt)
HttpRequest(host:"deb.debian.org")
HttpRequest(host:"security.debian.org")
HttpRequest(host:"archive.ubuntu.com")
HttpRequest(host:"*.archive.ubuntu.com")
HttpRequest(host:"security.ubuntu.com")
HttpRequest(host:"ports.ubuntu.com")
HttpRequest(host:"changelogs.ubuntu.com")
HttpRequest(host:"keyserver.ubuntu.com")
# OS package managers — Alpine (apk)
HttpRequest(host:"dl-cdn.alpinelinux.org")
HttpRequest(host:"*.alpinelinux.org")
# AI APIs
HttpRequest(host:"api.openai.com")
HttpRequest(host:"api.anthropic.com")
# GitHub (for git clone, releases)
HttpRequest(host:"github.com")
HttpRequest(host:"api.github.com", scheme:"https")
HttpRequest(host:"raw.githubusercontent.com")
HttpRequest(host:"objects.githubusercontent.com")
HttpRequest(host:"release-assets.githubusercontent.com", scheme:"https")
# Tilde API, install script, and releases
HttpRequest(host:"tilde.run", scheme:"https", path:"/api*")
HttpRequest(host:"tilde.run", scheme:"https", path:"/install*")
HttpRequest(host:"tilde.run", scheme:"https", path:"/releases*")
This policy is deny-by-default: any host not explicitly allowed is blocked. You can expand it by attaching additional allow policies, restrict it by attaching deny policies, or replace it entirely with your own custom policies.
Writing Network Policies¶
Network policies use the HttpRequest action from Tilde's policy DSL. They define allow and deny rules that are evaluated against each outbound HTTP/HTTPS request.
Available Modifiers¶
The HttpRequest action supports the following modifiers for matching requests:
| Modifier | Description | Example |
|---|---|---|
host |
Hostname (fnmatch pattern) | HttpRequest(host:"api.example.com") |
scheme |
"http" or "https" |
HttpRequest(scheme:"https") |
port |
Port number | HttpRequest(port:"443") |
method |
HTTP method | HttpRequest(method:"GET") |
All modifiers support fnmatch-style patterns (*, ?, [abc]).
Allow and Deny Rules¶
Policies use the same deny-overrides-allow semantics as RBAC:
- If any policy returns a deny (
!), the request is blocked - If at least one policy allows (and none deny), the request is allowed
- If no policy allows the request, it is blocked (default deny)
Examples¶
Allow an internal API¶
Block publishing to package registries¶
Prevent sandboxes from publishing packages while still allowing them to install dependencies:
!HttpRequest(host:"registry.npmjs.org", method:"POST")
!HttpRequest(host:"registry.npmjs.org", method:"PUT")
!HttpRequest(host:"pypi.org", method:"POST")
Allow a domain and all subdomains¶
# Allow example.com and *.example.com
HttpRequest(host:"example.com")
HttpRequest(host:"*.example.com")
Subdomain matching
Use *.example.com to match subdomains. A bare *example.com pattern would also match evilexample.com. Always use *.example.com (with the dot) for safe subdomain matching.
Allow HTTPS only¶
Tip
Do not embed secrets in policies. Use repository secrets or agent secrets to inject credentials into sandboxes.
Allow specific hosts with HTTPS only¶
Policy Resolution for Agents¶
When a sandbox runs as an agent, network policies use restrictive composition — a stricter model than RBAC's union-based merge:
- The
HttpRequestrules in the agent's inline policy are evaluated independently - The agent's creator's network policies (direct + group-inherited) are also evaluated independently
- The request is allowed only if both policy sets independently allow it
- The request is denied if either policy set denies it
Direct attachments and group memberships on the agent itself do not contribute to its network access — consistent with the RBAC intersection model. The agent's only source of network grants is the inline policy. If the inline has no HttpRequest allow rules, the sandbox cannot make any outbound HTTP requests, regardless of what the creator can reach.
This ensures an agent can never gain network access beyond what its creator has. If you (the creator) don't have a policy allowing api.internal.example.com, your agents can't reach it either — even if the agent's inline policy allows that host.
For non-agent principals (users, roles), only the principal's own policies apply.
Supported Protocols¶
| Protocol | Support |
|---|---|
| HTTP/1.1 | Fully policy-checked |
| HTTPS | Each request is individually policy-checked, including requests sent over a persistent connection |
WebSocket (ws://, wss://) |
Policy-checked on the initial Upgrade request; frames are then relayed without inspection |
| HTTP/3 (QUIC) | Not supported; QUIC (UDP 443) is blocked. HTTP/3-capable clients automatically fall back to HTTPS over TCP, which is fully supported |
HTTPS requests work transparently — standard tools (curl, Python requests, Node.js, Go, pip, npm, git) need no special configuration inside the sandbox.
Observability¶
Every proxied request produces a structured log entry with:
- Sandbox ID, method, scheme, host, port, path
- Decision (
allow,deny, orbaseline_deny) - Decision reason and source
- Names of matched allow/deny policies
- Upstream status code and latency
Denied requests are logged at the WARN level, making them easy to identify. Use these logs to:
- Discover which external services your sandboxes actually need
- Tune your allowlist based on real traffic patterns
- Investigate sandbox failures caused by blocked network requests
- Audit agent network activity for security reviews
Limits¶
| Resource | Limit |
|---|---|
| Request header size | 64 KB |
| WebSocket idle timeout | 5 minutes (no data in either direction) |
| Upstream connection timeout | 10 seconds |
| Upstream response header timeout | 30 seconds |
Next Steps¶
- Compute Isolation — container images, the sandbox API, triggers, and examples
- Filesystem Isolation — versioned storage mounts and session lifecycle
- RBAC Reference — set up agents, groups, and authorization policies