docs/src/trusted-network.md
Rama main · réplica de lectura del repositorio original.
# Trusted Network Mode
Trusted network mode gives sandbox containers filtered internet access
through a local HTTP proxy, so LLM-generated code can reach approved
domains (package registries, APIs) while everything else is blocked.
## Why
By default, sandbox containers run with `no_network = true` — full network
isolation. This is the safest option but breaks any task that needs to
install packages, fetch data, or call an API.
Setting `no_network = false` opens the network entirely, which defeats much
of the sandbox's purpose: a malicious command could exfiltrate data or
download additional payloads.
Trusted network mode sits between these extremes. It routes all outbound
traffic through a filtering proxy that only allows connections to domains
you explicitly trust.
```
┌──────────────┐ CONNECT ┌────────────┐ ┌──────────────┐
│ Sandbox │ ──────────────────▶ │ Proxy │ ────▶ │ github.com │ ✓
│ Container │ │ :18791 │ └──────────────┘
│ │ CONNECT │ │ ┌──────────────┐
│ HTTP_PROXY │ ──────────────────▶ │ Domain │ ──✗─▶ │ evil.com │ ✗
│ = proxy:18791 │ Filter │ └──────────────┘
└──────────────┘ └────────────┘
```
## Configuration
Enable trusted network mode in `moltis.toml`:
```toml
[tools.exec.sandbox]
network = "trusted"
trusted_domains = [
# Package registries
"registry.npmjs.org",
"pypi.org",
"files.pythonhosted.org",
"crates.io",
"static.crates.io",
# Git hosting
"github.com",
"gitlab.com",
# Common APIs
"api.openai.com",
"httpbin.org",
]
```
### Network policies
| Policy | Behavior | Use case |
|--------|----------|----------|
| *(empty / default)* | Uses legacy `no_network` flag | Backward compatible |
| `blocked` | No network at all | Maximum isolation |
| `trusted` | Proxy-filtered by domain allowlist | Development tasks |
| `open` | Unrestricted network | Fully trusted workloads |
```admonish warning title="open mode"
`network = "open"` disables all network filtering. Only use this when you
fully trust the LLM output or are running on a throw-away machine.
```
### Domain patterns
The `trusted_domains` list supports three pattern types:
| Pattern | Example | Matches |
|---------|---------|---------|
| Exact | `github.com` | Only `github.com` |
| Wildcard subdomain | `*.npmjs.org` | `registry.npmjs.org`, `www.npmjs.org`, etc. |
| Full wildcard | `*` | Everything (equivalent to `open` mode) |
## How the proxy works
When `network = "trusted"`, the gateway starts an HTTP CONNECT proxy on
`127.0.0.1:18791` at startup. Sandbox containers are configured to route
traffic through this proxy via `HTTP_PROXY` / `HTTPS_PROXY` environment
variables.
For each connection the proxy:
1. Extracts the target domain from the `CONNECT` request (or `Host` header
for plain HTTP).
2. Checks the domain against the allowlist in `DomainApprovalManager`.
3. If **allowed** — opens a TCP tunnel to the target and relays data
bidirectionally.
4. If **denied** — returns `403 Forbidden` and logs the attempt.
Both allowed and denied requests are recorded in the network audit log.
## Network Audit
Every proxied request is logged to an in-memory ring buffer (2048 entries)
and persisted to `~/.moltis/network-audit.jsonl`. The audit log is
accessible from:
- **Settings > Network Audit** in the web UI
- **RPC methods**: `network.audit.list`, `network.audit.tail`,
`network.audit.stats`
- **WebSocket events**: `network.audit.entry` streams entries in real time
### Audit entry fields
| Field | Description |
|-------|-------------|
| `timestamp` | ISO 8601 timestamp (RFC 3339) |
| `domain` | Target domain name |
| `port` | Target port number |
| `protocol` | `https`, `http`, or `connect` |
| `action` | `allowed` or `denied` |
| `source` | Why the decision was made (`config_allowlist`, `session`, etc.) |
### Filtering the audit log
The web UI provides real-time filtering by:
- **Domain** — free-text search across domain names
- **Protocol** — filter by `https`, `http`, or `connect`
- **Action** — show only `allowed` or `denied` entries
The RPC methods accept the same filter parameters:
```json
{
"method": "network.audit.list",
"params": {
"domain": "github",
"protocol": "https",
"action": "denied",
"limit": 100
}
}
```
### Audit stats
`network.audit.stats` returns aggregate counts:
```json
{
"total": 847,
"allowed": 812,
"denied": 35,
"by_domain": [
{ "domain": "registry.npmjs.org", "count": 423 },
{ "domain": "github.com", "count": 312 }
]
}
```
## Recommended domain lists
### Node.js / npm
```toml
trusted_domains = [
"registry.npmjs.org",
"*.npmjs.org",
]
```
### Python / pip
```toml
trusted_domains = [
"pypi.org",
"files.pythonhosted.org",
]
```
### Rust / cargo
```toml
trusted_domains = [
"crates.io",
"static.crates.io",
"index.crates.io",
]
```
### Git operations
```toml
trusted_domains = [
"github.com",
"gitlab.com",
"bitbucket.org",
]
```
```admonish tip title="Start narrow, widen as needed"
Begin with only the registries your project uses. The audit log will show
denied domains — add them to the allowlist only if they are legitimate.
```
## Relationship to other settings
- `no_network = true` (legacy) is equivalent to `network = "blocked"`.
When `network` is set, it takes precedence over `no_network`.
- `mode = "off"` disables sandboxing entirely — network policy has no
effect because commands run directly on the host.
- Resource limits (`memory_limit`, `cpu_quota`, `pids_max`) apply
independently of the network policy.
## Troubleshooting
**Proxy not starting**: Check the gateway startup log for
`trusted-network proxy started on port 18791`. If missing, verify
`network = "trusted"` is set in `moltis.toml`.
**Connections timing out**: Some tools don't respect `HTTP_PROXY`. Verify
the tool uses the proxy by checking the audit log — if no entries appear
for the domain, the tool is bypassing the proxy.
**Too many denied entries**: Review the audit log to identify legitimate
domains being blocked, then add them to `trusted_domains`.