Documentation
¶
Index ¶
- Constants
- func BoundedRedirects(maxHops int) func(*http.Request, []*http.Request) error
- func ClientForAllowPrivateIPs(timeout time.Duration, allowPrivateIPs bool) *http.Client
- func ContextWithSessionID(ctx context.Context, id string) context.Context
- func HTTPSOnlyRedirects(maxHops int) func(*http.Request, []*http.Request) error
- func IsPublicIP(ip net.IP) bool
- func LocalhostOnlyRedirects(maxHops int) func(*http.Request, []*http.Request) error
- func NewAllowPrivateIPsClient(timeout time.Duration) *http.Client
- func NewDesktopAwareSSRFSafeTransport() http.RoundTripper
- func NewHTTPClient(ctx context.Context, opts ...Opt) *http.Client
- func NewSSRFSafeTransport() *http.Transport
- func NewSafeClient(timeout time.Duration, unsafe bool) *http.Client
- func SSRFDialControl(_, address string, _ syscall.RawConn) error
- func SessionIDFromContext(ctx context.Context) string
- func SetOTelEnabled(enabled bool)
- func TracedClient(opts ...func(*http.Client)) *http.Client
- func TracedDefaultClient() *http.Client
- func TransportForAllowPrivateIPs(allowPrivateIPs bool) http.RoundTripper
- func WrapWithOTel(rt http.RoundTripper) http.RoundTripper
- type HTTPOptions
- type Opt
- func WithHeader(key, value string) Opt
- func WithHeaders(headers map[string]string) Opt
- func WithModel(model string) Opt
- func WithModelName(name string) Opt
- func WithProvider(provider string) Opt
- func WithProxiedBaseURL(value string) Opt
- func WithQuery(query url.Values) Opt
- func WithUnauthorizedRetry(refresh func(ctx context.Context, rejected string) (string, error)) Opt
Constants ¶
const DefaultToolHTTPTimeout = 30 * time.Second
DefaultToolHTTPTimeout is the HTTP client timeout used by the built-in HTTP-based toolsets (`fetch`, `api`, `openapi`, `a2a`) when the operator does not override it via `timeout:` in the agent config.
Centralised so the four toolsets agree on a single default — changing this value uniformly affects every HTTP-based built-in tool.
Variables ¶
This section is empty.
Functions ¶
func BoundedRedirects ¶ added in v1.55.0
BoundedRedirects returns an http.Client.CheckRedirect that limits a redirect chain to maxHops. SSRF on each redirect target is enforced by the transport's dialer; this only prevents infinite loops.
func ClientForAllowPrivateIPs ¶ added in v1.127.0
ClientForAllowPrivateIPs returns a client with an independent timeout and shared transport for the requested outbound address policy.
func ContextWithSessionID ¶ added in v1.55.0
ContextWithSessionID returns a new context carrying the given session ID. When set, [userAgentTransport.RoundTrip] forwards it as the `X-Cagent-Session-Id` header — but only on gateway-bound requests (those already carrying `X-Cagent-Forward`), to keep the identifier out of direct provider calls and unrelated outbound HTTP.
func HTTPSOnlyRedirects ¶ added in v1.55.0
HTTPSOnlyRedirects returns an http.Client.CheckRedirect that limits the redirect chain to maxHops AND rejects redirects whose Location is not https://. Use this when the original request is required to be HTTPS and a TLS downgrade through a Location header must be prevented.
func IsPublicIP ¶ added in v1.55.0
IsPublicIP reports whether ip is a routable public address. It rejects loopback (127/8, ::1), RFC1918 private ranges, link-local (incl. the 169.254.169.254 cloud metadata endpoint), multicast, the unspecified address (0.0.0.0, ::), CGNAT (100.64.0.0/10), IPv6 6to4, NAT64, and site-local prefixes.
func LocalhostOnlyRedirects ¶ added in v1.78.0
LocalhostOnlyRedirects returns an http.Client.CheckRedirect that limits the redirect chain to maxHops AND requires every redirect target to be an http://localhost URL. This prevents a localhost service from redirecting to internal network addresses (e.g. cloud metadata endpoints), which would bypass SSRF protection.
func NewAllowPrivateIPsClient ¶ added in v1.127.0
NewAllowPrivateIPsClient returns an HTTP client for explicit allow_private_ips opt-ins. It can reach private addresses directly, but uses Docker Desktop's PAC proxy when available; loopback is always direct. Docker Desktop remains optional and DOCKER_AGENT_DISABLE_DESKTOP_PROXY=1 restores the default environment-proxy/direct behavior.
func NewDesktopAwareSSRFSafeTransport ¶ added in v1.127.0
func NewDesktopAwareSSRFSafeTransport() http.RoundTripper
NewDesktopAwareSSRFSafeTransport returns a guarded transport that routes Docker-owned hostnames (docker.com, docker.io families) through Docker Desktop's PAC proxy when Desktop is available. All other hosts always use the direct SSRF-guarded transport (dial-time enforcement, defeats DNS rebinding). Docker Desktop is optional: absent, disabled, or when the target host is outside the allowlist, requests fall back to direct with the same SSRF protection as NewSSRFSafeTransport.
func NewSSRFSafeTransport ¶ added in v1.55.0
NewSSRFSafeTransport returns an http.Transport whose dialer enforces SSRFDialControl on every connection.
When http.DefaultTransport is a plain *http.Transport (the default), the returned transport is a Clone() of it, inheriting proxy, TLS, idle-pool and HTTP/2 settings. When DefaultTransport has been replaced by a wrapper (e.g. an application that swapped in otelhttp.NewTransport for global observability) the clone is not possible; the function falls back to a minimal transport with proxy support and emits a warning via log/slog. In either case the SSRF dial guard is active.
Use this for outbound HTTP that may follow attacker-influenced URLs (OpenAPI specs whose servers[] list is taken from the spec body, user-configured API endpoints, etc.). It does not enforce HTTPS — callers that require it must validate the request URL themselves and/or supply a CheckRedirect on the surrounding *http.Client.
As an exception, the explicitly-configured HTTP/HTTPS/ALL proxy is always dialable, even if it lives on a private address. Refusing to dial the operator-configured proxy adds no SSRF protection (the proxy enforces destination policy itself) and breaks sandboxes — like docker-agent's — whose mandatory egress proxy is on an RFC1918 IP.
func NewSafeClient ¶ added in v1.55.0
NewSafeClient returns the HTTP client used by built-in tools that issue outbound calls to URLs the operator (or a fetched OpenAPI spec) supplies.
On its direct path — Docker Desktop unavailable, disabled via DOCKER_AGENT_DISABLE_DESKTOP_PROXY, or the target host is outside the Docker-owned allowlist (docker.com and docker.io families) — the client refuses non-public IPs at dial time, defeating DNS rebinding to loopback / RFC1918 / link-local incl. cloud metadata at 169.254.169.254.
When Docker Desktop is running, only Docker-owned hostnames (docker.com, docker.io and their subdomains) go through its PAC proxy. There the only local control is a pre-request DNS preflight (see proxySafe): Desktop selects and resolves the destination itself, so dial-time enforcement does not apply. Either way the redirect chain is bounded at 10 hops.
When unsafe is true the client uses http.DefaultTransport. This branch exists ONLY for tests, which use [httptest.NewServer] (binds to 127.0.0.1) and therefore cannot pass the SSRF check.
func SSRFDialControl ¶ added in v1.55.0
SSRFDialControl is invoked by net.Dialer after DNS resolution but before the TCP handshake. It rejects addresses that are not safe to fetch from over the public internet.
Performing the check post-resolution defeats DNS rebinding: an attacker cannot point a public hostname at 127.0.0.1 or 169.254.169.254 to bypass us, because we re-validate the resolved IP itself.
func SessionIDFromContext ¶ added in v1.55.0
SessionIDFromContext returns the session ID stored on ctx by ContextWithSessionID, or the empty string if none is set.
func SetOTelEnabled ¶ added in v1.86.0
func SetOTelEnabled(enabled bool)
SetOTelEnabled toggles the gate consulted by WrapWithOTel. Called by `initOTelSDK` after providers and the propagator are wired so HTTP clients start injecting `traceparent` only once the rest of the SDK can actually use the resulting spans.
func TracedClient ¶ added in v1.86.0
TracedClient returns a configurable `http.Client` with the default transport already wrapped via `WrapWithOTel`. The supplied options (timeout, redirect policy, jar, etc.) are applied after construction. Convenience wrapper for short-lived clients with custom timeouts.
func TracedDefaultClient ¶ added in v1.86.0
TracedDefaultClient returns an `http.Client` equivalent to `http.DefaultClient` but with the default transport wrapped via `WrapWithOTel`. Use as a drop-in replacement at call sites that previously did `http.DefaultClient.Do(req)` so OAuth metadata fetches, fetch-tool requests, registry probes, and similar one-off HTTP calls chain into the active trace.
func TransportForAllowPrivateIPs ¶ added in v1.127.0
func TransportForAllowPrivateIPs(allowPrivateIPs bool) http.RoundTripper
TransportForAllowPrivateIPs returns the shared transport for the requested outbound address policy.
func WrapWithOTel ¶ added in v1.55.0
func WrapWithOTel(rt http.RoundTripper) http.RoundTripper
WrapWithOTel returns rt wrapped with otelhttp when OpenTelemetry has been enabled via `SetOTelEnabled` (called by `initOTelSDK`), or rt unchanged otherwise. Gating avoids per-request span allocation on the no-OTel path and stops sending a `traceparent` header to upstream LLM providers that have no use for it. Exposed so callers that build their own transports outside of `NewHTTPClient` can opt into the same gating without duplicating the check.
Types ¶
type HTTPOptions ¶
type Opt ¶
type Opt func(*HTTPOptions)
func WithHeader ¶
func WithHeaders ¶
func WithModelName ¶
func WithProvider ¶
func WithProxiedBaseURL ¶
func WithUnauthorizedRetry ¶ added in v1.125.0
WithUnauthorizedRetry re-authenticates and replays a request once when the server rejects the token it presented. refresh receives the rejected token and returns its replacement.