How It Works
The proxy acts as a reverse proxy for configured credential routes. The agent sends plain HTTP tolocalhost:<port>/<service>/... and the proxy:
- Strips the service prefix
- Injects the real credential as an HTTP header
- Forwards to the upstream over TLS
- Streams the response back
Quick Start
OPENAI_BASE_URL=http://127.0.0.1:<port>/openai in the child’s environment. Most LLM SDKs respect this variable and redirect API calls through the proxy automatically.
Storing Credentials
Credentials are stored in the system keyring under the service namenono. The username/account corresponds to the credential_key defined in network-policy.json:
| CLI Service | Keyring Username | Keyring Service |
|---|---|---|
openai | openai_api_key | nono |
anthropic | anthropic_api_key | nono |
gemini | gemini_api_key | nono |
google-ai | google_generative_ai_api_key | nono |
macOS
Linux
Thekeyring crate uses service, username, and target attributes. You must use these exact attribute names:
username (not account) as the attribute name. The target default attribute is required for the keyring crate to find the entry.
Environment Variables
When credential routes are configured, the proxy sets SDK-specific base URL environment variables:| Route | Environment Variable | Value |
|---|---|---|
| openai | OPENAI_BASE_URL | http://127.0.0.1:<port>/openai |
| anthropic | ANTHROPIC_BASE_URL | http://127.0.0.1:<port>/anthropic |
Credential Route Configuration
The built-innetwork-policy.json defines default credential routes:
| Service | Upstream | Header | Format |
|---|---|---|---|
| openai | https://api.openai.com/v1 | Authorization | Bearer |
| anthropic | https://api.anthropic.com | x-api-key | |
| gemini | https://generativelanguage.googleapis.com | x-goog-api-key | |
| google-ai | https://generativelanguage.googleapis.com | x-goog-api-key |
/v1 because the OpenAI SDK expects the base URL to include the version prefix. Anthropic’s SDK adds /v1/messages automatically, so its upstream is the root URL.
Using Credentials in Profiles
User profiles can specify which credential services to enable in thenetwork section:
Custom Credential Definitions
For APIs not covered by the built-in services, you can define custom credentials in your profile. This lets you use--proxy-credential with any API while keeping credentials out of the sandbox.
| Field | Required | Default | Description |
|---|---|---|---|
upstream | Yes | - | Upstream URL to proxy requests to (must be HTTPS, or HTTP for localhost only) |
credential_key | Yes | - | Keystore account name (alphanumeric and underscores only) |
inject_mode | No | header | Credential injection mode: header, url_path, query_param, or basic_auth |
inject_header | No | Authorization | HTTP header to inject the credential into (used with header and basic_auth modes) |
credential_format | No | Bearer {} | Format string for the credential value ({} is replaced with the credential) |
path_pattern | Conditional | - | Required for url_path mode. URL path pattern with {} placeholder (e.g., /bot{}/) |
path_replacement | No | - | Optional replacement pattern for url_path mode (e.g., /v2/bot{}/) |
query_param_name | Conditional | - | Required for query_param mode. Query parameter name for credential injection (e.g., key or api_key) |
custom_credentials). The credential name is used to generate environment variables like TELEGRAM_BASE_URL. Shell variable names cannot contain hyphens, so my-api would create MY-API_BASE_URL which cannot be referenced as $MY-API_BASE_URL in shell scripts. Use my_api instead.
Injection Modes
Custom credentials support multiple injection patterns to accommodate different API authentication schemes:Header Mode (default)
Injects the credential as an HTTP header with optional formatting. This is the most common authentication pattern.URL Path Mode
Replaces a phantom token in the URL path with the real credential. Useful for APIs like Telegram Bot API that embed authentication tokens in the path (e.g.,/bot{token}/method).
Query Parameter Mode
Adds or replaces a query parameter with the credential value. Common for APIs that use URL query parameters for authentication (e.g., Google Maps API).Basic Auth Mode
Injects a Base64-encoded Basic Authentication header. The credential value should be stored inusername:password format in the keystore.
username:password format:
Authorization: Basic <encoded>.
Phantom Token Validation
Forurl_path and query_param modes, the agent must include the session token (NONO_PROXY_TOKEN) as a placeholder in the request. The proxy validates this phantom token before replacing it with the real credential. Invalid or missing phantom tokens result in HTTP 401 Unauthorized responses.
Store the credential in the system keystore:
Security Validation
Custom credentials are validated at startup:- Upstream URL must be HTTPS (HTTP is only allowed for
localhost,127.0.0.1, or::1) - Credential key must be alphanumeric (letters, numbers, and underscores only)
Session Token Authentication
Reverse proxy requests are authenticated using anX-Nono-Token header containing the session token. The proxy generates a unique 256-bit token per session and passes it to the child via the NONO_PROXY_TOKEN environment variable. Every request to a credential route must include this header — requests without a valid token are rejected with 407 Proxy Authentication Required.
This prevents other localhost processes from accessing the credential injection routes.
Security Properties
- Credentials never enter the sandbox - The agent process has no access to API keys, even through environment variables or memory
- Session token isolation - Reverse proxy routes require
X-Nono-Tokenauthentication; CONNECT tunnels useProxy-Authorization - Keystore-backed storage - Credentials are loaded from the OS keyring (Keychain on macOS, Secret Service on Linux), not from plaintext files
- Zeroized in memory - Credential values are stored in
Zeroizing<String>and wiped from memory on drop - Session-scoped - Credentials are loaded once at proxy startup and never written to disk or logged
- Header stripping - The proxy strips any
Authorizationorx-api-keyheaders from the agent’s request before injecting the real credential, preventing the agent from overriding the injected value
Audit Logging
Reverse proxy requests are logged with the service name and status code, but credential values are never logged:Next Steps
- Network Filtering - Host-level network filtering
- Secrets Management - Storing credentials in the system keystore
- CLI Reference - Complete flag documentation including network flags