-
Notifications
You must be signed in to change notification settings - Fork 60
Description
Problem
When a sandbox network policy targets host.docker.internal as a destination, today the process requires two cumbersome steps:
- Add a policy rule for the hostname
- Wait for the environment to resolve
host.docker.internalto an IP, then update the policy to include that resolved IP (viaallowed_ips)—otherwise SSRF checks block the connection as private/internal
However, host.docker.internal is a special case in OpenShell. It is deliberately provisioned at cluster startup (via extra_hosts: ["host.docker.internal:host-gateway"] in Docker config, and included in PKI certificates and gateway metadata). Unlike arbitrary private network hosts, its IP is assigned by Docker and not known/controllable at policy authoring time, and it is explicitly intended to be reachable from sandboxes for local cluster routing.
Opportunity
Because host.docker.internal is an explicit and trusted part of the local cluster's topology—and is operator-configured, not open to arbitrary attacker control—it makes sense to loosen the SSRF protection for this one hostname.
Specifically: If a sandbox network policy names host.docker.internal, the proxy should allow CONNECT (and forward-proxy) egress to it without requiring an explicit IP in allowed_ips. The SSRF layer can resolve the current Docker gateway IP dynamically at runtime and allow only that, preserving defense-in-depth while removing an ergonomic obstacle for policy authors.
This change would:
- Reduce policy friction for a documented, first-class cluster endpoint
- Avoid brittle policies that break across environments or Docker restarts
- Align the SSRF logic with intended operator workflows
Proposed Solution
- Special-case
host.docker.internalin the SSRF check path: when this hostname is matched in a policy, resolve its IPs at connect-time and allow only those without furtherallowed_ipsoverride. (Never broaden to all private IPs, and never allow for arbitrary hostnames.) - Optionally: Document this behavior in the networking or policy architecture docs.
Relevant Code/Docs
- SSRF check:
resolve_and_reject_internal()andresolve_and_check_allowed_ips()incrates/navigator-sandbox/src/proxy.rs - OPA policy evaluation:
crates/navigator-sandbox/data/sandbox-policy.rego - Bootstrap/cluster provision:
cluster-bootstrap.sh, Dockerextra_hosts, PKI SANs - Design:
architecture/security-policy.md,architecture/sandbox.md
Risks and Mitigations
- Non-Docker Desktop environments: Not all Linux systems set up
host.docker.internalautomatically. However, OpenShell already adds it when provisioning the cluster for CI and production. - Leakage to true private hosts: Because this exception applies only to the literal
host.docker.internal, it doesn't weaken SSRF defenses for any attacker-influenced destinations.
Motivation/Impact
This change will streamline local development and multinode workflows, making sandbox egress policies for the Docker host simpler and more robust.
Alternative approaches
- Maintain current requirement for explicit
allowed_ips, but provide better UX or policy generation tooling to automate the lookup. This is less clean than encoding the topology trust directly in the SSRF enforcement path.
Background