Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agent-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2351,7 +2351,7 @@
},
"allow_private_ips": {
"type": "boolean",
"description": "Opt in to dialling non-public IP addresses (valid for type 'fetch', 'api', 'openapi', 'a2a', and remote MCP toolsets). By default protected HTTP clients refuse connections \u2014 after DNS resolution, so DNS rebinding is also blocked \u2014 to loopback, RFC1918 private ranges, link-local (including the cloud metadata endpoint at 169.254.169.254), multicast and the unspecified address. Set this to true when an agent legitimately needs to call internal services. For fetch, 'allowed_domains' / 'blocked_domains' are evaluated independently and still apply."
"description": "Opt in to dialling non-public IP addresses (valid for type 'fetch', 'api', 'openapi', 'a2a', and remote MCP toolsets). By default, on the direct path (Docker Desktop unavailable, disabled, or target host is not in the Docker-owned allowlist), protected HTTP clients refuse connections \u2014 after DNS resolution, defeating DNS rebinding \u2014 to loopback, RFC1918 private ranges, link-local (including the cloud metadata endpoint at 169.254.169.254), multicast and the unspecified address. When Docker Desktop is running, only Docker-owned hostnames (docker.com, docker.io families) go through its PAC proxy; dial-time enforcement does not apply on that path. Set this to true when an agent legitimately needs to call internal services. For fetch, 'allowed_domains' / 'blocked_domains' are evaluated independently and still apply."
},
"sudo_askpass": {
"type": "boolean",
Expand Down
2 changes: 1 addition & 1 deletion docs/community/troubleshooting/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ Model names must match the provider's naming exactly. Common mistakes:

### Network connectivity

If the agent hangs or times out, check that you can reach the provider's API endpoint. Firewalls, VPNs, or proxy settings may block requests.
If the agent hangs or times out, check that you can reach the provider's API endpoint. Firewalls, VPNs, or proxy settings may block requests. Docker Agent does not evaluate PAC files or URLs directly. When Docker Desktop is running, eligible requests use its PAC adapter before environment proxy settings; `NO_PROXY` does not bypass that selection. Set `DOCKER_AGENT_DISABLE_DESKTOP_PROXY=1` (or `true`, `yes`, or `on`) to restore `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` routing per request; see [Docker Desktop proxy](../../tools/fetch/index.md#docker-desktop-proxy) for scope and SSRF behavior.

## Tool Execution Failures

Expand Down
3 changes: 2 additions & 1 deletion docs/configuration/overview/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,12 @@ API keys and secrets are read from environment variables — never stored in con
| `DOCKER_AGENT_AUTO_UPDATE` | Set to a truthy value (`1`, `true`, `yes`, `on`) to let standalone release binaries self-update before running. See [Optional Self-Updates](../../getting-started/installation/index.md#optional-self-updates). |
| `DOCKER_AGENT_NO_TOKEN_EXCHANGE` | Set to `1` to stop Docker Agent from exchanging the access token stored by `docker login` for a Docker token. See [Docker authentication](../../guides/secrets/index.md#docker-authentication). |
| `DOCKER_AGENT_HUB_LOGIN_URL` | Point the token exchange at a Docker staging environment. Ignored unless it is an HTTPS `docker.com` URL. |
| `DOCKER_AGENT_DISABLE_DESKTOP_PROXY` | Set to a truthy value (`1`, `true`, `yes`, `on`) to bypass Docker Desktop's PAC adapter per request and restore standard `HTTP_PROXY`/`HTTPS_PROXY`/`ALL_PROXY`/`NO_PROXY` routing. |

> [!NOTE]
> **Legacy `CAGENT_*` aliases**
>
> The same variables are also accepted with the legacy `CAGENT_` prefix (e.g. `CAGENT_DEFAULT_MODEL`, `CAGENT_MODELS_GATEWAY`, `CAGENT_HIDE_TELEMETRY_BANNER`) for backward compatibility. Prefer the `DOCKER_AGENT_*` form in new setups.
> The same variables are also accepted with the legacy `CAGENT_` prefix (e.g. `CAGENT_DEFAULT_MODEL`, `CAGENT_MODELS_GATEWAY`, `CAGENT_HIDE_TELEMETRY_BANNER`) for backward compatibility. `DOCKER_AGENT_DISABLE_DESKTOP_PROXY` is the exception: it has no legacy `CAGENT_*` alias. Prefer the `DOCKER_AGENT_*` form in new setups.

> [!IMPORTANT]
> Model references are case-sensitive: `openai/gpt-5` is not the same as `openai/GPT-5`.
Expand Down
4 changes: 4 additions & 0 deletions docs/features/api-server/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ Each agent entry in the `GET /api/agents` response contains:
| `multi` | boolean | `true` when the config defines more than one agent. |
| `commands` | array of string | Sorted list of named command keys defined on the root agent. Omitted when no commands exist. |

### Remote agent sources

For an agent loaded from a remote HTTP(S) configuration source, endpoints that need to load that source return `502 Bad Gateway` when fetching it fails. A missing configured agent returns `404 Not Found`; invalid source URLs or configuration return `500 Internal Server Error`.

### Sessions

| Method | Path | Description |
Expand Down
2 changes: 2 additions & 0 deletions docs/features/remote-mcp/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ For full configuration details, see the [Tool Config](../../configuration/tools/

Set `allow_private_ips: true` on a remote MCP toolset only when the MCP server or its OAuth registration/token endpoints intentionally resolve to private, loopback, or link-local addresses. The default blocks those OAuth helper requests to reduce SSRF risk.

When Docker Desktop is running, eligible OAuth discovery, registration, token exchange, refresh, and helper requests use its PAC adapter before environment proxy settings. It does not apply to remote MCP Streamable HTTP/SSE transport. Set `DOCKER_AGENT_DISABLE_DESKTOP_PROXY=1` (or `true`, `yes`, or `on`) to restore standard `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` routing; `NO_PROXY` does not bypass Desktop PAC selection. Docker Agent does not evaluate PAC files or URLs directly—see [Docker Desktop proxy](../../tools/fetch/index.md#docker-desktop-proxy).

> [!NOTE]
> **Headers forwarded during OAuth discovery**
>
Expand Down
2 changes: 2 additions & 0 deletions docs/tools/a2a/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ The `Authorization` header shown above authenticates to endpoints served with `d
| `name` | string | ✗ | Tool name registered for the remote agent. Defaults to a name derived from the server's agent card. |
| `headers` | map\[string\]string | ✗ | Extra HTTP headers sent with every request (useful for `Authorization`, tenant selection, tracing, \u2026). |

When Docker Desktop is running, eligible requests use its PAC adapter before environment proxy settings. Set `DOCKER_AGENT_DISABLE_DESKTOP_PROXY=1` (or `true`, `yes`, or `on`) to restore standard `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` routing; `NO_PROXY` does not bypass Docker Desktop PAC selection. Docker Agent does not evaluate PAC files or URLs directly—see [Docker Desktop proxy](../fetch/index.md#docker-desktop-proxy).

> [!TIP]
> **See also**
>
Expand Down
4 changes: 3 additions & 1 deletion docs/tools/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ agents:
- Default 30-second timeout per request (override with the `timeout` field)
- Only HTTP and HTTPS URLs are supported
- No support for file uploads or multipart forms
- By default, requests to non-public IP ranges (loopback, RFC1918, link-local, the cloud-metadata endpoint, multicast, the unspecified address) are refused at dial time — even when DNS for an otherwise-public host resolves there. Set `allow_private_ips: true` to disable that check.
- On its direct path, requests to non-public IP ranges (loopback, RFC1918, link-local, the cloud-metadata endpoint, multicast, the unspecified address) are refused at dial time — even when DNS for an otherwise-public host resolves there. Set `allow_private_ips: true` to disable that check.

## Reaching internal services

Expand All @@ -241,6 +241,8 @@ toolsets:
>
> Setting `allow_private_ips: true` re-exposes the SSRF surface for this tool. Only enable it when the configured `endpoint` is a trusted internal service — a prompt-injected agent cannot redirect the call elsewhere because the endpoint is fixed in config, but redirects from the configured host can still reach unexpected places.

When Docker Desktop is running, eligible public destinations use its PAC proxy before standard environment-proxy routing. A PAC `DIRECT` response selects Docker Desktop's direct egress. `NO_PROXY` does not bypass Desktop PAC selection; set `DOCKER_AGENT_DISABLE_DESKTOP_PROXY=1` (or `true`, `yes`, or `on`) to bypass only the Desktop adapter per request and restore standard `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` routing. Loopback always stays direct. For guarded requests, Docker Desktop PAC routing is restricted to Docker-owned hostnames (docker.com and docker.io families); all other hosts use the direct SSRF-guarded path. Within the allowed set, local DNS preflight requires public addresses before Docker Desktop is selected; all lookup failures — including NXDOMAIN, empty results, errors, and private or mixed answers — stay on the SSRF-protected direct path. This preflight does not validate Docker Desktop-selected egress, whether PAC selects a proxy or `DIRECT`. `allow_private_ips: true` removes that direct-path address guard for trusted internal services, but Desktop PAC still takes precedence for eligible non-loopback destinations. See [Docker Desktop proxy](../fetch/index.md#docker-desktop-proxy).

> [!TIP]
> **For Complex APIs**
>
Expand Down
12 changes: 10 additions & 2 deletions docs/tools/fetch/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,19 @@ toolsets:
> [!NOTE]
> **Already blocked by default**
>
> You do **not** need to add loopback, RFC1918, link-local (incl. `169.254.169.254`), multicast or the unspecified address to `blocked_domains` to be safe — the fetch tool already refuses connections to those ranges at dial time, after DNS resolution. The example above is only useful if you also want to reject those hosts _before_ any network call (and to surface a clearer error message to the agent), or if you have set `allow_private_ips: true` and want to deny a specific subset.
> You do **not** need to add loopback, RFC1918, link-local (incl. `169.254.169.254`), multicast or the unspecified address to `blocked_domains` to protect the fetch tool's SSRF-guarded direct path: it refuses those resolved addresses at dial time. When an eligible request is routed through Docker Desktop's PAC proxy, that proxy selects and enforces its own destination policy. The example above is useful if you also want to reject those hosts _before_ any network call (and to surface a clearer error message to the agent), or if you have set `allow_private_ips: true` and want to deny a specific subset.

### Docker Desktop proxy

When Docker Desktop is running, remote HTTP(S) agent configuration sources and built-in HTTP toolsets send eligible public destinations through its PAC proxy before normal environment-proxy routing. A PAC `DIRECT` result selects Docker Desktop's direct egress. `NO_PROXY` does not bypass Desktop PAC selection; set `DOCKER_AGENT_DISABLE_DESKTOP_PROXY=1` (or `true`, `yes`, or `on`) to bypass only the Desktop adapter per request and restore standard `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` routing. Loopback always stays direct.

For guarded clients, Docker Desktop PAC routing is restricted to Docker-owned hostnames (docker.com and docker.io families); all other hosts use the direct SSRF-guarded path regardless of Desktop state. Within the allowed set, local DNS preflight requires one or more public addresses before Docker Desktop is selected; all lookup failures — including NXDOMAIN, empty results, errors, and private or mixed answers — stay on the SSRF-protected direct path. This preflight does not validate Docker Desktop-selected egress, whether PAC selects a proxy or `DIRECT`. `allow_private_ips: true` removes the direct-path address guard for trusted internal services, but Desktop PAC still takes precedence for eligible non-loopback destinations.

For Docker Desktop proxy configuration, see [Docker Desktop proxy settings](https://docs.docker.com/desktop/settings-and-maintenance/settings/#proxies). Docker's [PAC files](https://docs.docker.com/enterprise/security/hardened-desktop/air-gapped-containers/#proxy-auto-configuration-pac-files) documentation describes the `containersProxy` setting for managed container and image-pull traffic, not Docker Agent's host-proxy adapter path.

### SSRF protection and reaching localhost

By default, the fetch tool refuses connections to **non-public IP addresses** — even when DNS for an otherwise-public host resolves to one of them (so DNS rebinding is also blocked). The check happens at dial time, after DNS resolution, and rejects:
By default, the fetch tool's **direct path** refuses connections to **non-public IP addresses** — even when DNS for an otherwise-public host resolves to one of them (so DNS rebinding is also blocked). This dial-time check applies when Docker Desktop is unavailable or bypassed. Docker Agent does not evaluate PAC, so egress selected by Docker Desktop — through a proxy or with PAC `DIRECT` — is outside this local dial-time enforcement. The check rejects:

- **Loopback** — `127.0.0.0/8`, `::1` (this is what blocks `http://localhost/...` and `http://127.0.0.1/...`)
- **RFC1918 private ranges** — `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`
Expand Down
2 changes: 2 additions & 0 deletions docs/tools/mcp/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ toolsets:

For a curated list of public remote MCP endpoints (Linear, GitHub, Vercel, Notion, …) and full OAuth configuration details, see [Remote MCP Servers](../../features/remote-mcp/index.md).

When Docker Desktop is running, eligible MCP OAuth discovery, token, and helper requests use its PAC adapter before environment proxy settings, but remote MCP Streamable HTTP/SSE transport does not. Set `DOCKER_AGENT_DISABLE_DESKTOP_PROXY=1` (or `true`, `yes`, or `on`) to restore standard `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` routing; `NO_PROXY` does not bypass Docker Desktop PAC selection. Docker Agent does not evaluate PAC files or URLs directly—see [Docker Desktop proxy](../fetch/index.md#docker-desktop-proxy).

## MCP Prompts

MCP servers can expose **prompts** — named, parameterized templates that the server provides via the `/prompts` endpoint. Docker Agent discovers these at toolset startup and registers them as **slash commands** in the TUI, so you can invoke them directly from the input box.
Expand Down
4 changes: 3 additions & 1 deletion docs/tools/openapi/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ toolsets:

### Reaching internal services

By default the OpenAPI tool refuses connections to non-public IP addresses, blocking SSRF attempts even when DNS resolves an otherwise-public host to an internal range. Opt in with `allow_private_ips` when the spec or its `servers` entries legitimately target localhost or your internal network:
By default, the OpenAPI tool's **direct path** refuses connections to non-public IP addresses, including a public hostname that resolves to an internal address. Docker Agent does not evaluate PAC, so the dial-time guard applies when Docker Desktop is unavailable or bypassed; egress selected by Docker Desktop — through a proxy or with PAC `DIRECT` — is outside local dial-time enforcement. Opt in with `allow_private_ips` when the spec or its `servers` entries legitimately target localhost or your internal network:

```yaml
toolsets:
Expand All @@ -56,6 +56,8 @@ toolsets:
allow_private_ips: true
```

When Docker Desktop is running, eligible public destinations use its PAC proxy before standard environment-proxy routing. A PAC `DIRECT` response selects Docker Desktop's direct egress. `NO_PROXY` does not bypass Desktop PAC selection; set `DOCKER_AGENT_DISABLE_DESKTOP_PROXY=1` (or `true`, `yes`, or `on`) to bypass only the Desktop adapter per request and restore standard `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` routing. Loopback always stays direct. For guarded requests, Docker Desktop PAC routing is restricted to Docker-owned hostnames (docker.com and docker.io families); all other hosts use the direct SSRF-guarded path. Within the allowed set, local DNS preflight requires public addresses before Docker Desktop is selected; all lookup failures — including NXDOMAIN, empty results, errors, and private or mixed answers — stay on the SSRF-protected direct path. This preflight does not validate Docker Desktop-selected egress, whether PAC selects a proxy or `DIRECT`. `allow_private_ips: true` removes that direct-path guard for trusted internal services, but Desktop PAC still takes precedence for eligible non-loopback destinations. See [Docker Desktop proxy](../fetch/index.md#docker-desktop-proxy).

## Properties

| Property | Type | Required | Description |
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ require (
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
go.yaml.in/yaml/v4 v4.0.0-rc.6
golang.org/x/crypto v0.54.0 // indirect
golang.org/x/net v0.57.0 // indirect
golang.org/x/net v0.57.0
golang.org/x/text v0.41.0 // indirect
golang.org/x/time v0.15.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
Expand Down
16 changes: 10 additions & 6 deletions pkg/config/latest/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1603,12 +1603,16 @@ type Toolset struct {
// For the `fetch`, `api`, `openapi`, `a2a` and remote `mcp` toolsets — opt in
// to dialling non-public IP addresses.
//
// By default, protected HTTP clients refuse connections (after DNS
// resolution, so DNS rebinding is also blocked) to loopback (127/8,
// ::1), RFC1918 private ranges, link-local — including the cloud
// metadata endpoint at 169.254.169.254 — multicast and the unspecified
// address. Set this to true to permit those addresses, which is required
// when an agent legitimately needs to call internal services.
// By default, on the direct path (Docker Desktop unavailable, disabled, or
// target host is not in the Docker-owned allowlist), protected HTTP clients
// refuse connections — after DNS resolution, defeating DNS rebinding — to
// loopback (127/8, ::1), RFC1918 private ranges, link-local — including the
// cloud metadata endpoint at 169.254.169.254 — multicast and the unspecified
// address. When Docker Desktop is running, only Docker-owned hostnames
// (docker.com, docker.io families) go through its PAC proxy; dial-time
// enforcement does not apply on that path. Set this to true to permit
// non-public addresses, which is required when an agent legitimately needs to
// call internal services.
//
// For `fetch`, `allowed_domains` and `blocked_domains` are evaluated
// independently of this flag: even with `allow_private_ips: true`, an
Expand Down
Loading
Loading