Network Policy
Gatekeeper enforces network policy to control which hosts a client can reach through the proxy. Policy evaluation happens before credential injection — blocked requests never receive credentials.
Permissive vs Strict
The policy field controls the default behavior:
| Mode | Behavior |
|---|---|
permissive | All hosts are allowed. This is the default. |
strict | Only hosts in the allow list are reachable. All other requests are denied with a 407 response. |
network:
policy: strict
allow:
- api.github.com
- "*.anthropic.com"
In permissive mode, the allow list is ignored. All traffic passes through.
Allow List Mechanics
The allow list is a set of host patterns. Each pattern follows the same matching rules as credential host patterns:
- Exact match.
api.github.commatches onlyapi.github.com. - Wildcard.
*.github.commatches any subdomain:api.github.com,raw.githubusercontent.comdoes not match (different base domain), butfoo.bar.github.comdoes. - Port-specific.
api.example.com:8080matches only that port. Patterns without a port match only ports 80 and 443.
When a client sends a CONNECT request, gatekeeper extracts the host and port and checks them against the allow list. If no pattern matches, the tunnel is refused.
Grant Hosts Are Auto-Allowed
When callers pass grant names to SetNetworkPolicy, gatekeeper expands each grant to its known host patterns and adds them to the allow list automatically. This is used by moat’s daemon layer, which passes per-run grants when registering runs.
For example, the github grant expands to:
github.comapi.github.com*.githubusercontent.com*.github.com
In standalone mode (gatekeeper.yaml), grant expansion does not apply — only the explicit allow list is used. Add credential hosts to the allow list manually when using strict mode.
Interaction with Credential Injection
Network policy and credential injection are independent checks that run in sequence:
- Network policy runs first. If the host is denied, the request is blocked with a
407response. No credential lookup occurs. - Credential injection runs second, only for allowed requests. The proxy matches the host against credential patterns and injects headers.
This ordering has a security property: credentials are never sent to unauthorized hosts. Even if a credential pattern matches a host that is blocked by network policy, the credential is never injected because the request never reaches the injection step.
Per-Path Rules
When gatekeeper has path-level rules (configured via RequestChecker), it evaluates them on the inner HTTP request after TLS interception — not on the CONNECT tunnel. The CONNECT request only carries the host, not the path. Gatekeeper intercepts the tunnel, reads the plaintext request, and then checks method and path against the rules.
Note: Per-path rules require TLS interception (a CA must be configured). Without interception, only host-level allow/deny applies. Gatekeeper logs a warning if path rules are configured but the CA is missing.
Host Gateway Policy
When a request targets a host gateway address (synthetic hostname or loopback), gatekeeper applies a separate check: the destination port must be in the run’s AllowedHostPorts list. This prevents containers from reaching arbitrary services on the host machine. See Host Gateway for details.
Blocked Response Format
Blocked requests receive a 407 Proxy Authentication Required response with a Proxy-Authenticate: Moat-Policy header and a plaintext body explaining which host was denied. The X-Moat-Blocked header indicates the denial reason (request-rule for network policy, host-service for host gateway blocks).