Approved Egress
Approved egress blocks direct internet access from dedicated Kubernetes workers and sends their traffic through a policy-enforcing HTTP proxy.
A worker can reach a hostname only when it is on the static allowlist or a human has approved a temporary grant in Matrix.
Use it when worker-routed tools such as shell and python must not reach arbitrary hosts.
Enable with the Runtime Chart
workers:
backend: kubernetes
sandbox:
proxyToken:
existingSecret: mindroom-sandbox-proxy
key: MINDROOM_SANDBOX_PROXY_TOKEN
approvedEgress:
enabled: true
image:
tag: v0.1.10
allowlist:
domains:
- example.com
- .docs.example.com
maxTtlSeconds: 21600
The chart deploys the proxy, points worker proxy settings at it, and adds NetworkPolicies so workers cannot bypass it.
Approved egress requires workers.backend: kubernetes, a pinned approvedEgress.image.tag or approvedEgress.image.digest, and a token from approvedEgress.token.existingSecret or workers.sandbox.proxyToken.
Use proxy image v0.1.10 or later, because browser tools tunnel every connection with CONNECT and older images refuse plain-HTTP pages with TCP_DENIED/403.
approvedEgress.maxTtlSeconds caps every temporary grant and defaults to 21600 (6 hours).
The chart also enables the built-in approved_egress toolkit at runtime, including with config.data or config.existingConfigMap, so you do not edit config.yaml.
It appends approved_egress to defaults.tools, or to the built-in default tools when defaults.tools is omitted, and adds a tool_approval rule that requires Matrix approval for request_network_access.
Agents with include_default_tools: false do not get the toolkit.
These runtime additions are not written to config.yaml when you save from the dashboard or API.
Set approvedEgress.manageRuntimeConfig: false to keep the proxy wiring without these additions, for example when your config assigns approved_egress to specific agents.
Static Allowlist
Set allowlist entries in approvedEgress.allowlist.domains, or provide them in approvedEgress.allowlist.existingConfigMap under the key named by approvedEgress.allowlist.key (default allowed-domains.txt); you cannot set both.
A plain hostname matches exactly, and a leading dot such as .docs.example.com matches the domain and all its subdomains.
Allowlisted hostnames never need approval.
Changing approvedEgress.allowlist.domains restarts the proxy automatically when you apply the chart, but edits to an existingConfigMap reach the proxy only after you restart it.
MindRoom keeps the allowlist it started with until its own pod restarts, so a removed domain is still reported as allowed and gets no grant in the meantime; the runtime chart README names the Deployments to restart.
Requesting Access
Agents call request_network_access(hostnames, ttl_minutes, reason) with every blocked external hostname the task needs, up to 20 per call, and one Matrix approval covers the whole batch.
Hostnames must be exact external DNS names; schemes, ports, paths, wildcards, IP literals, single-label names, localhost, cluster-local names, and cloud metadata hostnames are rejected, and one invalid hostname rejects the whole request.
Hostnames already on the static allowlist are skipped, and when every requested hostname is allowlisted the tool replies that no grant is needed without asking for approval.
The granted TTL is the requested ttl_minutes, capped at the deployment maximum, and the reply says when the cap applied.
Who a grant covers depends on the agent's effective worker scope, which comes from private.per for private agents, then the agent's worker_scope, then defaults.worker_scope:
| Effective scope | Grant applies to |
|---|---|
user_agent |
The requester's own worker for that agent |
shared or unset |
That agent's worker |
user |
Not supported; the request fails with approved egress is not supported for worker_scope=user |
Temporary Full Access
The allow_full_access tool option defaults to false.
Enable it in the tool's settings or in an authored tool entry, on defaults.tools or on an individual agent:
Agents can then call request_network_access(hostnames=["*"], ttl_minutes=5, reason="Install dependencies").
The "*" must be the only entry.
Full-access requests always require Matrix approval, use the same TTL cap, and apply to the same workers as hostname grants.
They open all public hostnames on ports 80 and 443 through the proxy, while private networks, internal hostnames, and other ports and protocols stay blocked.
The proxy image must support full-access grants; older images reject them.
When a grant expires, new connections need an allowlist match or another grant, but established connections, including HTTPS tunnels, stay open.
Without the Runtime Chart
Enable the toolkit by setting MINDROOM_APPROVED_EGRESS_ENABLED=true, or author the same configuration yourself:
defaults:
tools:
- approved_egress
tool_approval:
default: auto_approve
rules:
- match: request_network_access
action: require_approval
You can assign approved_egress to individual agents instead of defaults.tools.
The toolkit reads these environment variables, which the runtime chart sets for you:
| Variable | Purpose | Default |
|---|---|---|
MINDROOM_APPROVED_EGRESS_ENABLED |
Add the toolkit and approval rule at runtime, as described above | unset |
MINDROOM_APPROVED_EGRESS_API_URL |
Proxy policy API URL; plain http is allowed only for loopback or in-cluster service names |
http://mindroom-egress-proxy:8080 |
MINDROOM_APPROVED_EGRESS_TOKEN |
Bearer token for the policy API | required |
MINDROOM_APPROVED_EGRESS_ALLOWLIST |
Comma-separated static allowlist, used instead of the file when set | unset |
MINDROOM_APPROVED_EGRESS_ALLOWLIST_PATH |
Static allowlist file with one entry per line and # comments |
/etc/mindroom-egress/allowed-domains.txt |
MINDROOM_APPROVED_EGRESS_MAX_TTL_SECONDS |
Maximum grant TTL | 21600 |
Agent Vault Chaining
When approved egress and Agent Vault are used together, the chain must be:
Squid must be first because temporary grants are matched to the worker by its source IP. If traffic goes through Agent Vault first, Squid sees only the vault's IP, so temporary grants never match while static allowlist entries still work.
Before enabling the Agent Vault server and bootstrap job, create the Secret named by workers.kubernetes.agentVault.bootstrapSecretName (default agent-vault-bootstrap) with both AGENT_VAULT_MASTER_PASSWORD and AGENT_VAULT_OWNER_PASSWORD.
Create it in the worker namespace too when that differs from the release namespace.
workers:
backend: kubernetes
sandbox:
proxyToken:
existingSecret: mindroom-sandbox-proxy
key: MINDROOM_SANDBOX_PROXY_TOKEN
kubernetes:
agentVault:
enabled: true
cliImage: infisical/agent-vault:<pinned>
ownerEmail: owner@example.test
server:
enabled: true
bootstrap:
enabled: true
kubectlImage: bitnami/kubectl:<pinned>
workerCaConfigMapName: agent-vault-ca
approvedEgress:
enabled: true
image:
tag: v0.1.10
parentProxy:
enabled: true
host: agent-vault
port: 14322
With approvedEgress.parentProxy.enabled: true, workers send Agent Vault traffic to approved egress first.
After the allowlist and grant check, requests carrying the worker's Agent Vault token go on to the vault, which still validates the token and injects credentials, while requests without a token go directly to the internet.
Use approvedEgress.parentProxy.bypassDomains (default empty) for destinations such as signed URLs that must skip credential injection:
approvedEgress:
parentProxy:
enabled: true
bypassDomains:
- downloads.example.test
- .objects.example.test
Entries match like allowlist entries: exact hostnames, or a leading dot for a domain and its subdomains.
Use ASCII domain names without schemes, ports, paths, * wildcards, or whitespace.
Bypassed destinations still need an allowlist match or grant, and changing bypassDomains restarts the proxy automatically.
Do not point Agent Vault tool traffic directly at the chart-managed Agent Vault proxy while approved egress is enabled.
The chart refuses that combination with approvedEgress with Agent Vault must be squid-first: enable approvedEgress.parentProxy so Squid sees worker source IPs for dynamic grants, or set workers.kubernetes.agentVault.proxyUrl to an external/custom proxy URL explicitly.
An external or custom workers.kubernetes.agentVault.proxyUrl remains allowed.
Secure Minimum
Beyond the chart's required settings:
- Keep
workers.kubernetes.networkPolicy.create,egressProxy.networkPolicy.create, andapprovedEgress.networkPolicy.createenabled. - Keep
request_network_accessbehindtool_approval. - Put hostnames that should never need approval on the static allowlist.
- Keep
approvedEgress.maxTtlSecondsshort.