Skip to main content

Documentation Index

Fetch the complete documentation index at: https://theseventeen-2abbdf80.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

In keychain-auth, no binary is trusted by default. When you register a new binary, it receives an empty policy — it cannot read, write, or search anything until you explicitly grant those permissions. This is the zero-trust principle: access is denied unless it has been approved.

What zero-trust means in practice

Zero-trust here means two things:
  1. Every binary is verified before it can connect. The daemon checks the binary’s SHA-256 hash at connection time. If the hash doesn’t match a registered entry, the connection is rejected immediately.
  2. Every permission is explicit and scoped. Even a registered binary can only access the specific service namespaces you allow. A binary approved to read openai secrets cannot read your aws secrets, and a read-only binary cannot write or delete anything.
This protects you from compromised dependencies. A malicious npm package or pip post-install script running under your user account cannot silently harvest your keychain — it isn’t registered, and even if it were, it would have no permissions.

The config.json schema

Policies live in ~/.config/keychain-auth/config.json. Each registered binary has its own entry in the registered_binaries array.
{
  "protocol_version": "1",
  "registered_binaries": [
    {
      "path": "/usr/local/bin/my-cli",
      "hash": "sha256:a3f1c9...",
      "registered_at": "2026-05-21T09:00:00Z",
      "allowed_read_services": ["aws", "openai"],
      "allowed_write_services": ["openai"],
      "can_search": false
    },
    {
      "path": "/usr/local/bin/agentsecrets",
      "hash": "sha256:abcd1234...",
      "registered_at": "2026-05-21T10:00:00Z",
      "allowed_read_services": ["AgentSecrets"],
      "allowed_write_services": ["AgentSecrets"],
      "can_search": true
    }
  ]
}

Field reference

FieldTypeDescription
pathstringAbsolute path to the binary on disk.
hashstringSHA-256 hash of the binary, prefixed with sha256:. Updated when you run keychain-auth upgrade.
registered_atstringISO 8601 timestamp of when the binary was registered.
allowed_read_servicesarray of stringsService namespaces this binary may read from.
allowed_write_servicesarray of stringsService namespaces this binary may write to or delete from.
can_searchbooleanWhether this binary may list keys or use prefix-based operations.
The daemon re-reads config.json on every new client connection, so changes you make to the file take effect immediately — no daemon restart required. When editing manually, ensure the JSON is valid before saving to avoid startup errors on the next connection.

Permission scopes

Each action type maps to a specific policy requirement:
  • Read — the requested service must appear in allowed_read_services
  • Write — the requested service must appear in allowed_write_services
  • Delete — the requested service must appear in allowed_write_services (delete is treated as a write-level privilege)
  • Searchcan_search must be true and the service must be in allowed_read_services
  • Prefix read or prefix delete — requires both the relevant service permission and can_search: true, because the daemon must enumerate keys to resolve the prefix
A binary with only read access to a service cannot write, delete, or overwrite secrets in that namespace. Compromise of a read-only binary does not give an attacker write access.

Batch atomicity: all-or-nothing pre-flight checks

Before the daemon performs any keychain operation, it checks every target in the request against your policy. If even one target would be denied, the entire batch is rejected — no reads or writes occur. This means you cannot accidentally expose a partial set of secrets. Either the whole request succeeds, or nothing happens.
{
  "type": "RESPONSE",
  "status": "denied",
  "reason": "service_not_allowed"
}

The pending approval workflow

When an unregistered binary connects to the daemon, it is not silently dropped. keychain-auth:
  1. Rejects the connection with unregistered_binary_pending_approval
  2. Records the binary in ~/.config/keychain-auth/pending.json, including its SHA-256 hash, binary path, CLI arguments, and a timestamp (entries expire after 24 hours)
  3. Keeps the entry available for you to inspect and act on
You can review pending binaries at any time:
keychain-auth list-pending
If you recognise the binary and want to allow it, approve it by hash:
keychain-auth approve <hash>
This adds the binary to config.json with an empty policy — no services are granted yet. You then edit the config to grant the permissions you want. This deliberate two-step process means you can never accidentally grant broad access by approving an unknown binary.
If you are distributing a CLI tool that integrates with keychain-auth, add keychain-auth register $(which your-cli-tool) to your installer. This registers the binary at install time so users don’t hit the pending approval flow on first run.

Keeping policies up to date after upgrades

When a binary is updated, its SHA-256 hash changes. The next time it connects, keychain-auth will not recognise it and will reject it as unregistered. Run the upgrade command after installing a new version of a registered binary:
keychain-auth upgrade $(which your-cli-tool)
This updates the stored hash in config.json without touching the existing permission policy.