Every read, write, delete, search, and rejected connection attempt is written to a local audit log in structured JSON format. The log gives you a precise, per-operation record of what accessed your keychain, when, and whether it was allowed — without ever writing the secret values themselves.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.
Where the audit log lives
| Platform | Default path |
|---|---|
| Linux | ~/.local/share/keychain-auth/audit.log |
| macOS | ~/Library/Logs/keychain-auth/audit.log |
The log directory is created automatically by the daemon with permissions
0700. Only your user account can read it.Log format
Each entry is a single JSON object on its own line (newline-delimited JSON). The file is append-only; new entries are added to the end as operations occur.Fields
| Field | Type | Description |
|---|---|---|
timestamp | string | ISO 8601 UTC timestamp of when the operation was processed (nanosecond precision). |
action | string | The operation type: connect, read, write, delete, or search. |
pid | number | The kernel-verified process ID of the calling binary. |
binary_path | string | Absolute path of the calling binary on disk. |
binary_hash | string | SHA-256 hash of the calling binary, prefixed with sha256:. |
service | string | The keychain service namespace that was targeted (e.g. aws, AgentSecrets). |
targets | array of strings | The key names that were requested. For search operations, these are the keys returned — never their values. |
result | string | GRANTED, DENIED, or ERROR. |
reason | string | Present only when result is DENIED or ERROR. Explains why the operation was rejected. |
Example log entries
A successful write followed by a successful read, then a denied attempt from an unregistered binary:write entry at 01:00:15Z records the target key name — not the value that was stored. The read entry at 01:01:22Z records that the read was granted — not the secret that was returned.
Secrets are never written to the log
This is a deliberate security boundary. Even if someone gains read access to your audit log file, they cannot harvest credentials from it. The log is useful for forensic investigation and anomaly detection without becoming a second place where your secrets are exposed.Why search logs key names, not values
Search operations return a list of matching key names (targets) to the caller — never the corresponding secret values. The audit log reflects exactly what was returned: the key names only. This design limits blast radius. If a binary with search permission is compromised, an attacker can discover that a key namedprod/stripe-key exists, but they cannot retrieve its value through a search alone. To read the actual secret, they need a separate read request — and that read generates its own audit log entry.
This means the audit log captures granular, per-secret access records rather than opaque “search batch granted” entries. Each read for a specific key appears as a separate line in the log, making it straightforward to answer questions like “which process read my AWS production key at 3am?”
What a search entry looks like
What a search entry looks like
A search that found two keys logs the target names, not the values:The subsequent reads each generate their own entry:
What a denied connection looks like
What a denied connection looks like
When an unregistered binary attempts to connect, keychain-auth logs the rejection before closing the connection:The binary is also queued in
~/.config/keychain-auth/pending.json for your review.Using the log for security monitoring
Because every entry includesbinary_path, binary_hash, and pid, you can:
- Detect unexpected binaries reading secrets they shouldn’t know about
- Correlate access patterns with specific process IDs from your system logs
- Confirm that a deployed binary’s hash matches the approved hash in your config
- Identify
DENIEDentries that indicate active probing by unregistered processes