Skip to main content
Routes define which outbound requests cordon intercepts and what credentials to inject. Each route matches on a destination hostname and specifies an auth type. Prefer cordon route add and cordon route edit over hand-editing routes in cordon.toml. The CLI validates hostnames, auth types, headers, secret-source fields, and scoped match fields such as path and method filters. The TOML below is the reference format when you need to inspect, review, or automate outside the CLI.

Route structure

When auth.secret.source is "1password", the following fields are available:

Auth types

Header auth

Injects a configured header with the secret value. Set scheme for Authorization: Bearer <secret> style headers, or omit it for raw API-key headers.

Basic auth

Injects an Authorization: Basic <base64(username:secret)> header.

Raw API key header

Injects a custom header with the secret value.
header_name must be a valid HTTP field name and cannot be one of Cordon’s reserved credential injection headers: Host, Content-Length, Transfer-Encoding, Connection, Keep-Alive, TE, Trailer, Upgrade, Proxy-Authorization, or Proxy-Authenticate.

How matching works

  • Cordon first matches on the hostname of the outbound request after canonicalization (case-insensitive, trailing dot ignored).
  • Exact host entries match one hostname only. Host entries containing * are globs where * matches zero or more characters within a single hostname label. For example, "*.stripe.com" matches "api.stripe.com" but not "stripe.com" or "deep.api.stripe.com".
  • A configured host match is the operator’s trust decision for credential injection, SSRF denylist exemption, and CONNECT interception. To prevent the most common footguns, cordon rejects host globs where a wildcard label is not followed by at least two literal labels: "*.com", "*.app", and "foo.*" are rejected; "*.vercel.app", "api-*.stripe.com", and "*.preview.acme.com" are accepted.
This rule does not enforce public suffix awareness. Patterns such as "*.vercel.app", "*.github.io", or "*.herokuapp.com" pass the check but match subdomains owned by different parties — every Vercel project, GitHub user, or Heroku app under those suffixes. Use the narrowest pattern your workflow allows, such as "<your-project>-*.vercel.app", when you need to scope to deployments you control.
  • Configure at most one path matcher: path_exact for one endpoint, or path_glob for variable segments (use "/v1/**" for “match everything under this subtree”).
  • Configs written by Cordon 0.4.0 may contain path_prefix. Cordon still accepts that legacy field. Prefixes that can be represented exactly as globs are rewritten as path_glob when the config is saved; other legacy prefixes keep prefix semantics to avoid broadening credential scope.
  • If path_exact is set, the normalized request path must exactly equal that path.
  • If path_glob is set, * must be a complete path segment and matches exactly one non-empty path segment. ** must also be a complete path segment and matches zero or more whole path segments. For example, "/v1/*/comments/**" matches "/v1/post/comments" and "/v1/post/comments/123", but not "/v1/comments", "/v1/a/b/comments/123", or "/v1/post-*/comments".
  • Encoded traversal such as "/v1/%2e%2e/admin" does not match scoped paths. Encoded path separators such as "%2F" or "%5C" are treated as non-matches because Cordon forwards the original URI upstream. Paths that would still contain encoded dots or path separators after one decode, such as "/v1/%252e%252e/admin", are also treated as non-matches for credential injection.
  • Literal backslashes are also treated as non-matches for scoped paths because some upstream servers interpret them as path separators. Empty path segments are preserved, so //v1/charges does not match /v1/charges.
  • If methods is set, the request method must exactly match one of the configured uppercase method tokens.
  • On a full route match (host plus any configured path and method filters), cordon strips Authorization, Proxy-Authorization, and the configured credential header, then injects the managed credential.
  • If the host matches but path or method filters do not, the request is not Cordon-managed credential traffic. It passes through without origin-auth stripping or injection.
  • Unmatched requests are forwarded without modification.
  • Routes are evaluated in order; the first full match wins. Place more-specific routes before broad catch-all routes for the same host. The CLI appends new routes, so reorder cordon.toml manually if a broad route was added first.
For HTTPS CONNECT traffic, Cordon uses the CONNECT authority to decide whether a configured host should be MITM-intercepted. Path and method filters are evaluated only after the inner HTTPS request is decrypted, so unmatched paths or methods pass through the tunnel without credential stripping or injection.
Configured HTTP route hosts are explicit trust decisions. In v1, requests to a configured route host bypass private/link-local/loopback SSRF denylist checks so internal APIs, VPN/private endpoints, PrivateLink services, staging environments, and localhost development services continue to work even when a request does not satisfy optional path or method credential-injection filters. For non-credentialed access to denylist-blocked destinations, see denylist_exceptions instead. DNS pinning still applies, but DNS pinning is not private-IP blocking. Routes authorize credential injection and upstream selection for the configured host; they do not protect against malicious same-user callers. Post-v1 private-upstream policy work will revisit this default.
Auth stripping is unconditional on full route matches. If your application sends Authorization: Bearer placeholder to a request that satisfies host, path, and method filters, cordon removes it and injects the real token. Requests outside those filters are forwarded unchanged.
Route names share one namespace with PostgreSQL listener names and must be unique. See Listeners for PostgreSQL listener configuration.

Provider auth quick reference

Use the auth type expected by the upstream API, even if your app or agent only sends a dummy credential. Cordon strips any inbound credential on full route matches and injects the real value from the configured secret source. If an application needs a provider-specific env var to select an auth path, set a placeholder such as dummy-replaced-by-cordon. The placeholder is not trusted: Cordon removes it and injects the real credential.

Route changes and secret rotation

Cordon loads route definitions when the proxy starts. Restart Cordon after adding or editing routes. HTTP route secrets are fetched per request, so rotating the secret value in 1Password or the keyring does not require a restart. PostgreSQL listener secrets are different; see Secret Sources.

Multiple routes

You can configure multiple routes for different APIs: