op). This guide covers setup, configuration, the security model for agent workflows, and troubleshooting.
For the OS keyring alternative, see Secret Sources.
Prerequisites
Before configuring 1Password as a secret source, you need:- A 1Password account with a vault containing the secrets you want to inject.
-
The 1Password CLI (
op) installed:
- An authenticated session — either interactive or via a service account:
- Verify the session works:
Cordon does not handle 1Password authentication. The
op CLI must have a valid session before cordon start. If the session expires, Cordon must be restarted after re-authenticating.Configuration
Per-route secret reference
Each route that uses 1Password specifies the vault, item, and field:| Field | Description |
|---|---|
vault | 1Password vault name |
item | Item name within the vault |
field | Field label within the item (case-sensitive) |
Provider configuration (optional)
By default, Cordon finds theop binary by searching your PATH. If op is not on PATH — common when running as a background service via launchd or systemd — specify the path explicitly:
Complete example
How it works
Cordon resolves all 1Password secrets at startup, not per-request:- Cordon locates the
opbinary (from the configuredpathor by searchingPATH). - For each route with
source: 1password, Cordon runs: - The JSON response’s
valuefield is extracted and wrapped in Cordon’sSecrettype, which zeroizes memory on drop and redacts on all log output. - The
opCLI is not called again after startup. Secrets are held in memory for the proxy’s lifetime.
Authentication methods
Interactive sign-in
cordon start will fail with an op error — re-authenticate and try again.
Service accounts
Security considerations
What Cordon protects
When using Cordon with 1Password, credentials are injected at the HTTP layer — the agent process never handles secret values. Specifically, Cordon keeps the following out of the agent’s environment variables, logs, and request headers:- The credential value (injected after the request leaves the agent’s process)
- Any
Authorizationheader value (stripped and replaced unconditionally for matched routes)
cordon.yaml on disk — a same-user agent with file or shell access could read the config file and discover them. This is a limitation of the local same-user trust model, not credential exposure.
The op CLI attack surface
Cordon invokes the op CLI as a subprocess. Whether other processes can reuse that authenticated session depends on how op is configured:
- Desktop app integration (biometric): The
opCLI communicates with the 1Password desktop app over a local socket. While the app is unlocked, any same-user process can invokeopand authenticate through the same socket. - Shell-based sign-in (
eval $(op signin)): The session token is stored in a shell environment variable (OP_SESSION_*). Only processes that inherit that variable can reuse it — other terminals and independently launched processes cannot. - Service accounts (
OP_SERVICE_ACCOUNT_TOKEN): Only processes with this environment variable can authenticate.
Mitigations
Scope service account access. If using a service account, grant it access only to the specific vault items Cordon needs. A compromised agent can only reach items the service account can access. Consider the OS keyring on macOS. macOS Keychain enforces per-application access control lists (ACLs) on keychain entries. By default, only the binary that created an entry can read it silently — other binaries trigger a system authorization dialog requiring user approval. This means an agent process callingsecurity find-generic-password to read an entry created by the cordon binary would prompt the user visibly, providing an opportunity to deny access. See Secret Sources — OS Keyring.
Restrict agent shell access where possible. Some agents support permission modes that limit arbitrary command execution:
- Claude Code’s permission system can restrict tool use
- Codex offers a sandboxed execution mode
- IDE-based agents (Cursor) can limit terminal access through configuration
op CLI access. Unexpected access patterns may indicate an agent attempting to read vault items directly.
Future direction
A direct SDK integration — compiling 1Password access into Cordon’s binary rather than shelling out toop — is being explored. This would eliminate the external CLI as an attack vector by keeping the authenticated session inside Cordon’s process memory, inaccessible to other processes. This integration does not exist today; the op CLI is the current integration path.
Workflow
- Store the secret in 1Password (create a vault, item, and field if needed).
- Install and authenticate the
opCLI (see Prerequisites). - Configure the route in
cordon.yamlwithsource: 1passwordand the vault/item/field names. - Start Cordon:
cordon start— secrets are fetched from 1Password at startup. - Route traffic through the proxy — credentials are injected transparently.
Diagnostics
Troubleshooting
op exited with status 1
op exited with status 1
The
op CLI returned an error. Common causes:- Session expired: Re-authenticate with
eval $(op signin)and restart Cordon. - Vault not found: Verify the vault name matches exactly (case-sensitive). Check with
op vault list. - Item not found: Verify the item name matches exactly. Check with
op item list --vault "VaultName". - Permission denied: The signed-in account or service account lacks access to the vault. Check vault permissions in the 1Password app.
op error output directly to the terminal — read the error message for specifics.1Password CLI (op) not found
1Password CLI (op) not found
The
op binary is not on PATH. Solutions:- Install it:
brew install --cask 1password-cli(macOS) or see the 1Password CLI install guide. - Specify the path explicitly in your config under
secrets.providers(see Provider configuration). - Background services:
launchdandsystemdservices have a minimalPATH. Use an explicitpathin the provider config, or add theopdirectory to the service’sPATH.
which op in your shell to find the binary location.Secrets not updating after rotation
Secrets not updating after rotation
Cordon fetches secrets once at startup. After rotating a credential in 1Password:
- Stop Cordon:
cordon stop - Restart:
cordon start
Service account not working
Service account not working
OP_SERVICE_ACCOUNT_TOKEN must be set in the environment where Cordon runs.- Shell:
export OP_SERVICE_ACCOUNT_TOKEN="..." && cordon start - launchd: Add an
EnvironmentVariablesentry to the plist. - systemd: Use
systemctl --user edit cordon-default.serviceto add anEnvironment=line in the override, then restart the service withsystemctl --user restart cordon-default.service. Replacedefaultwith your instance name if you used--nameduring setup.
OP_SERVICE_ACCOUNT_TOKEN="..." op vault listWrong secret value injected
Wrong secret value injected
The Look for the
field value in your config must match the field label in 1Password exactly (case-sensitive).Inspect the item’s fields to find the correct label:label property on each field in the JSON output. Common mistakes:- Using
passwordinstead ofcredential(or vice versa) - Using a section name instead of a field label
- Case mismatch (e.g.,
Secret_Keyvssecret_key)