Charon is a forward proxy that adds credentials to approved outbound requests. It lets a workload call an API without putting the API credential in that workload's environment, filesystem, or container image.
AI agents are workloads from Charon's point of view. Charon can give an agent narrowly scoped access to an authenticated API without placing the long-lived credential inside the agent runtime. The same model works for CLIs, builds, development containers, and other programs.
The workload sends a harmless placeholder instead of a real credential. Charon checks a short-lived signed authorization, matches the request against local policy, obtains the credential from the configured secret store, and replaces the placeholder only in the request sent upstream.
workload Charon API
no stored credential ──▶ verify + apply policy ──▶ authenticated request
placeholder only resolve credential
Charon is an early-stage project. Its core proxy, authorization, HTTPS interception, provider adapter, and tests are implemented. The deployment and integration contracts are still being refined before a production release.
AI agents and other software often need authenticated access to external services such as email, calendars, cloud platforms, customer-support systems, payment providers, or an organization's own APIs. Giving every workload a long-lived credential makes that credential available to the workload and to anything that compromises it.
Charon moves the credential into a smaller, separately operated process. A request is allowed only when all of these agree:
- a signed, short-lived, single-use workload manifest;
- a named capability in Charon's configuration; and
- the actual destination hostname, HTTP method, and path.
The workload cannot choose a secret, a secret-store item, or an unconfigured destination. Charon does not return credentials to workloads and does not follow redirects after adding one.
These names appear in the configuration and protocol:
| Term | Meaning |
|---|---|
| Workload | The program making the outbound request, such as an AI agent, CLI, build, or development container. |
| Manifest | A short-lived, signed authorization carried with one request. It identifies the workload and names one capability. Each manifest can be used once. |
| Capability | A named permission in Charon's local policy, for example “read the current GitHub user.” It maps to one service and an exact set of methods and paths. |
| Service | A configured destination and credential-injection rule: exact hostnames, the credential header, its placeholder, and a secret reference. |
| Secret provider | The adapter Charon uses to obtain a credential. The current implementations are an environment provider for disposable development and a Vaultwarden provider. |
| Realm | One isolated Charon deployment: a process, configuration, secret-provider session, and policy. |
The current pre-1.0 manifest also carries tenant, persona, workspace, and lease identifiers supplied by the issuer. They are integration context, not secret selectors or core Charon concepts. This part of the public contract is under review before 1.0.
- A trusted issuer gives the workload a signed manifest for a named capability.
- The workload sends a normal proxy request to Charon with
Proxy-Authorization: Charon <manifest>and the configured public placeholder in the credential header. - Charon verifies the signature, expiry, realm identity, and single-use nonce.
- Charon resolves the capability from its own configuration and checks the request's exact host, method, and path.
- Charon asks its configured provider for the policy-owned secret reference.
- Charon replaces the placeholder in the upstream request and returns the API's response.
For HTTPS, the workload connects through Charon using HTTP CONNECT and trusts
the operator-provided Charon CA. The
forward-proxy contract specifies the complete wire
protocol. Charon's ordinary health endpoints are described by
OpenAPI.
The project requires Rust 1.97 or newer. mise is optional; it installs the pinned toolchain and provides short names for common development commands.
mise install
mise run checkmise run <task> means “run a task defined in mise.toml.” For example,
mise run dev runs the task named dev:
mise run devThat command is equivalent to:
cargo run -- --config examples/charon.dev.tomlThe development configuration listens only on 127.0.0.1:3129, uses the
environment provider, and contains no real credential. It is suitable for
starting the process and inspecting its health endpoints; exercising an
authenticated proxy request also requires issuing a valid test manifest.
Run the individual checks directly if you do not use mise:
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-features
cargo deny checkexamples/charon.dev.toml is a minimal local
configuration. examples/charon.toml shows the
Vaultwarden, TLS, identity, capability, and service settings used in an
operator-managed deployment.
Configuration is deny-by-default:
- destination hosts are exact names; wildcards are not supported;
- capabilities list exact HTTP methods and paths;
- remote destinations require HTTPS on port 443;
- redirects are disabled;
- request and response bodies have independent size limits; and
- unknown configuration fields are rejected.
Secret stores sit behind the Rust SecretProvider interface. An adapter
receives an opaque reference chosen by local policy and returns a
SecretString; callers never choose a backend item.
The binary currently includes:
environment, intended only for disposable local development; andvaultwarden, using an isolated Bitwarden CLI session and exact item UUID mappings.
More backends can be added without changing the workload protocol. Providers are compiled into the binary and selected by trusted realm configuration; Charon does not load credential-handling plugins dynamically or fall back to a different provider during an outage. The extension rules are documented in ADR 0004.
Charon owns the request-time data path: manifest verification, local policy, credential lookup, injection, proxying, and redacted audit events.
It does not own:
- user, workspace, or lease management;
- issuance of workload manifests;
- secret-store provisioning and backup;
- deployment or network policy; or
- human-approval workflows.
Those systems integrate through signed data and versioned contracts; Charon does not query an application's database on the request path. See the integration boundary map and machine-readable contracts.
Charon handles credentials, so changes to authorization, proxying, provider
adapters, TLS, or logging deserve careful review. Please read
SECURITY.md before reporting a vulnerability and see the
threat model for the detailed guarantees, assumptions,
and remaining risks.
The full local quality gate is:
mise run check- Documentation index
- Contributing
- Forward-proxy protocol
- Configuration and integration boundaries
- Threat model
- Deployment guide
- Architecture decisions
- Human-approval contracts
Charon is licensed under the MIT License.
