> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cynative.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cynative Outbound Proxy: HTTPS_PROXY and NO_PROXY Setup

> Configure HTTPS_PROXY, HTTP_PROXY, and NO_PROXY for Cynative — what traffic routes through the proxy and what an intercepting proxy can observe.

All connector traffic in Cynative — the requests the model issues through `http_request`, credential discovery and refresh, authorization-data downloads, startup probes, and Kubernetes ClusterRole fetches — routes through a single proxy policy set by the operator at startup. The policy is read once when the process starts; nothing the model sends can change it.

***

## Proxy variables

| Variable | Meaning |
| - | - |
| `https_proxy` / `HTTPS_PROXY` | Proxy for `https://` targets — which is every connector request Cynative makes. |
| `http_proxy` / `HTTP_PROXY` | Proxy for `http://` targets. Cynative itself issues none; some SDK metadata probes do. |
| `no_proxy` / `NO_PROXY` | Comma-separated list of targets that bypass the proxy. |

**Lowercase wins.** When both casings are set and non-empty, the lowercase spelling takes precedence — the behavior of `curl` and Go's `x/net`. Go's standard library reads the uppercase spelling first, and some SDK helpers (such as MSAL's optional regional-authority autodetection) follow that reading. To avoid disagreements, **set both spellings to the same value**.

`NO_PROXY` entry formats:

* `*` — everything goes direct
* An IP address or CIDR — matched against requests whose host is an IP literal (never against what a name resolves to)
* A hostname — matches the name and all its subdomains
* `.hostname` — subdomains only
* `host:port` — matches that host and port specifically

`localhost` (lowercase) and loopback literals are never proxied regardless of `NO_PROXY`. Trailing dots matter: an entry `api.example.com` does not match a request for `api.example.com.`. A value containing a control character is rejected at startup.

***

## Supported proxy URL formats

```
http://proxy.corp:3128
http://user:password@proxy.corp:3128
socks5://proxy.corp:1080
socks5h://proxy.corp:1080
proxy.corp:3128                     # bare hostname — treated as http://
```

An `https://` proxy (TLS to the proxy itself) is **rejected at startup**. This is because Go would reuse the connector's TLS settings — a cluster's private CA, an mTLS client certificate, a custom `tls-server-name` — for the proxy hop, and no documentation makes that safe. The startup error names the variable and the fault, and never prints the value.

***

## What routes through the proxy

| Traffic | Routed by the proxy policy |
| - | - |
| `http_request` calls the model makes | Yes — one route decision per request |
| GitHub and GitLab token probes at startup, OpenAPI description downloads | Yes |
| EKS, GKE, AKS, and self-managed Kubernetes ClusterRole fetches | Yes |
| AWS SDK calls (STS, IAM, EKS, `AssumeRole`), IAM policy document, service reference, IAM dataset, and API model archive downloads | Yes |
| Google ADC discovery and token refresh, IAM roles service, GKE service, Discovery catalog, tokeninfo probe | Yes |
| Azure credential chain (environment, workload identity, managed identity), ARM role definitions, managed clusters, ARM catalog | Yes |

***

## What does NOT route through the proxy

| Traffic | Reason |
| - | - |
| Google Compute Engine metadata client (`169.254.169.254` or `GCE_METADATA_HOST`) | The GCP SDK metadata client never uses a proxy — by design, it only contacts the local link-local address. |
| `gh`, `glab`, `az`, `azd`, `pwsh` helper processes, AWS `credential_process`, Google executable-sourced credentials | These are separate child processes that inherit the environment and manage their own proxy behavior. |
| The LLM connection | The model connection is configured separately via Bifrost's `proxy_config` block. See [LLM providers](/providers/overview) for details. |

**Instance metadata services** (`169.254.169.254`) sit on a link-local address that only answers for the host that asks — a request sent through a proxy on another machine would reach the wrong machine's metadata or nothing. On EC2 or Azure hosts, add the metadata address to `NO_PROXY`:

```sh theme={null}
export HTTPS_PROXY=http://proxy.corp:3128
export NO_PROXY=169.254.169.254,10.0.0.0/8,.corp.example
```

***

## Trust boundary

A **direct connection** (including `NO_PROXY` matches) keeps every check Cynative performs: the host is pinned to the connector, the action is authorized, the credential is attached only after both, and the resolved IP address is verified before the connection is made.

A **proxied connection** keeps the host pin, the action authorization, and the credential injection — but the connection itself goes only to the proxy the operator named. Cynative never resolves the destination host itself and never verifies its address; both are delegated to the proxy. The proxy sees the authority (`CONNECT host:port`) of every connection.

A **plain CONNECT proxy** (non-intercepting) cannot read the request inside the TLS tunnel; the origin certificate is verified against the connector's trust settings exactly as on a direct connection.

***

## What an intercepting proxy can observe

An intercepting proxy — one whose certificate the connector's trust settings accept — occupies a privileged position in the traffic path. It can observe:

* **Credentials** — Cynative attaches credentials after the action gate authorizes the request. Because the connection goes to the proxy, the proxy receives the full request including any `Authorization` header or signed query parameter. Credentials reach the proxy in plain text inside the TLS tunnel the proxy terminates.
* **Request URLs** — the full request URL, method, and headers for every connector call.
* **Response bodies** — every response body, before Cynative's redaction runs.

<Warning>
  An intercepting proxy can also **rewrite responses**, including the authorization data the client-side action gate is built from. A rewritten ClusterRole, IAM policy document, or permission catalog widens what the gate allows, defeating the read-only guarantee. Only route Cynative through a proxy you would trust with the credentials themselves.
</Warning>

***

## SOCKS proxy notes

Both `socks5://` and `socks5h://` hand the **unresolved destination name** to the proxy — Go never resolves the target host locally for either spelling. Destination name resolution is entirely the proxy's responsibility.

The SOCKS5 handshake carries authentication credentials subject to these length limits:

* **Username**: 1 to 255 bytes
* **Password**: at most 255 bytes

A SOCKS proxy URL with credentials outside these limits is rejected at startup rather than failing every dial.

Proxy credentials in the URL are sent to the proxy as HTTP Basic (for `http://`) or SOCKS authentication over the plaintext proxy hop. Cynative never prints them. Credentials echoed back in error text are scrubbed before the text reaches the model, the inventory, or the audit log.

***

## Certificate trust

Cynative verifies the origin certificate with the operating system's root store plus the connector's own CA when it has one (the cluster CA from a kubeconfig, `connectors.gitlab.ca_cert`). A TLS-intercepting corporate proxy therefore works once its CA is added to the OS trust store.

On Linux — and since Go 1.27 on macOS and Windows as well — `SSL_CERT_FILE` and `SSL_CERT_DIR` replace the platform store rather than extend it, so a bundle named there must include the public roots as well. `GODEBUG=x509sslcertoverrideplatform=0` restores the earlier macOS and Windows behavior where the platform verifier ignores those two variables.

***

## Proxy startup audit line

When a proxy is configured, the connector inventory prints a summary line at startup:

```
  ~ egress      https_proxy http://proxy.corp:3128 · no_proxy 10.0.0.0/8,169.254.169.254
```

An unusable setting stops the run before any connector registers:

```
  ✗ egress      HTTPS_PROXY: unsupported scheme "https"; use http://, socks5:// or socks5h://
```

Every audited `http_request` result also carries `route: "proxy"` or `route: "direct"` — the routing decision for that specific request. A request denied before route selection (host, action, or credential rejection) carries no `route` field.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.