Secret store
Kenaz holds onto a fair number of secret values — provider API keys, MCP server credentials, OAuth tokens, the audit log signing key. None of them sit in plaintext on disk. This page is the reference for what is stored, where, and how to inspect or clear it.
Backend
Kenaz uses your operating system's native credential store. There is no Kenaz-specific encryption layer on top — we lean on the OS for the at-rest crypto.
| OS | Backend | Where to inspect |
|---|---|---|
| macOS | Keychain Services (login keychain) | Keychain Access app → login → search kaneaz-harness |
| Windows | Credential Manager | Credential Manager → Windows Credentials → look for kaneaz-harness:* |
| Linux | Secret Service API (libsecret) | seahorse (GNOME), kwalletmanager5 (KDE), or secret-tool search application kaneaz-harness |
If the OS keychain is locked, Kenaz cannot read its own secrets and will prompt for an unlock when needed (typical on first launch after login).
What's stored
Every entry follows the same shape: a service name (always kaneaz-harness), an account name (the locator below), and the secret blob.
| Locator | What it is | Created when |
|---|---|---|
provider:<id>:api_key | API key for a configured provider | You add a provider |
provider:<id>:aws_access_key / …:aws_secret_key / …:aws_session_token | Bedrock IAM credentials when configured | Bedrock provider with long-term keys or assume-role |
mcp:<id>:env:<KEY> | An env var typed into an MCP server's environment block | You save an MCP server with envs |
mcp:<id>:oauth:access_token / …:refresh_token | OAuth tokens for MCP servers that use the Kenaz credential resolver | OAuth grant on first use |
audit:signing_key | Ed25519 private key that signs exported audit bundles | First launch |
update:keypair | Local update verification keypair | First launch |
consent:gdpr_v1 | (docs/marketing site only — lives in localStorage, not keychain) | — |
How values get in
Several entry points, all converging on the same flow:
- UI accepts plaintext (Provider editor, MCP env block, OAuth callback).
- Plaintext is written to the OS keychain via the platform-native API.
- The plaintext buffer is zeroed in memory.
- The on-disk config (
providers.json,mcp.json, etc.) is updated to record only the keychain locator — never the plaintext.
The on-disk config is plain JSON readable by your user but contains no secret material — only references.
How values are used
Two patterns:
- Resolved on demand. When a provider needs to call its API, Kenaz looks up
provider:<id>:api_key, sets the bearer header, makes the request, and discards the resolved value when the request finishes. - Resolved on spawn. When an MCP server starts, Kenaz resolves all
mcp:<id>:env:*entries and injects them into the child process's environment. The plaintext exists in memory only as long as the child runs; on shutdown the process exits and the env table goes away.
In neither case does plaintext get written back to disk.
Inspecting & clearing
macOS
# List every Kenaz entry
security find-generic-password -s 'kaneaz-harness' -g 2>&1 | head -20
# Delete one by account name
security delete-generic-password -s 'kaneaz-harness' -a 'provider:my-anthropic:api_key'
# Delete every Kenaz entry (use with care)
while security delete-generic-password -s 'kaneaz-harness' 2>/dev/null; do : ; done
You'll be prompted to allow the security CLI to read each entry the first time.
Windows (PowerShell)
# List Kenaz entries
cmdkey /list:kaneaz-harness*
# Delete one
cmdkey /delete:kaneaz-harness:provider:my-anthropic:api_key
# Delete every Kenaz entry
cmdkey /list:kaneaz-harness* | ForEach-Object {
if ($_ -match 'Target: (kaneaz-harness:.*)') {
cmdkey /delete:$($Matches[1])
}
}
Linux
# List
secret-tool search --all application kaneaz-harness
# Delete one
secret-tool clear application kaneaz-harness account provider:my-anthropic:api_key
# Delete every Kenaz entry
secret-tool search --all --unlock application kaneaz-harness | \
awk -F': ' '/^attribute.account/{print $2}' | \
xargs -I{} secret-tool clear application kaneaz-harness account {}
GUI alternatives: seahorse (GNOME) or kwalletmanager5 (KDE) — search for "kaneaz-harness" in either.
Inside Kenaz
The Settings view has a Secrets tab that mirrors the keychain entries Kenaz manages:
- Inventory — list of every locator Kenaz wrote, with the entry kind, last-used timestamp, and the on-disk config it backs.
- Rotate — for provider API keys: prompts for a new value, updates the keychain entry, the on-disk config locator stays the same. Useful for rotating without breaking session history.
- Clear orphans — finds entries Kenaz wrote that no longer have an on-disk config referencing them (e.g. you deleted a provider but the keychain entry got left behind). Removes them.
- Wipe — nuclear: delete every Kenaz keychain entry. Equivalent to the OS-native commands above. Use when offboarding a machine.
What is not in the secret store
- The audit log itself. Plaintext SQLite at
<data_dir>/audit/audit.db. Sensitive content lives there because the audit log's job is to capture what happened, including the prompts/responses you'd want to retrieve later. See Audit log for retention controls. - Session messages, attachments, artifacts. Plaintext on disk under
<data_dir>/sessions/. They aren't secrets in the same sense — they're your conversation history. Disk encryption (FileVault, BitLocker, LUKS) is the right layer for protecting these at rest. - Provider config (
providers.json, etc.). Plaintext, but contains only metadata + keychain locators — no secret values.
If your threat model needs at-rest encryption beyond the OS keychain (a shared workstation, a recovered drive, a forensics scenario), enable full-disk encryption.
Backups & migration
The OS keychain is not automatically synced or backed up. If you set up Kenaz on a new machine you'll re-paste your API keys. This is intentional — secret material that follows you across machines without your explicit action is a worse default than mild inconvenience on machine moves.
If you want to migrate, the fastest path is:
- Export your
providers.json,mcp.json, and other Kenaz configs from$XDG_CONFIG_HOME/kaneaz-harness/(these contain no secrets, just locators and structure). - On the new machine, drop them into the same directory.
- Open Kenaz; each provider/MCP shows up greyed out as "missing credential."
- Click each one → re-paste. Done.
Threat model boundaries
Kenaz's secret store is designed against:
- Casual filesystem access —
cat ~/.config/kaneaz-harness/providers.jsonreveals zero secrets. - Memory dumps after process exit — secrets are only resident for the lifetime of the process / request that needs them.
- Curl-the-config-into-a-pastebin — same as above; the on-disk config is safe to share for debugging without redaction (modulo provider IDs and model names).
It is not designed against:
- Local malware running as your user. Anything with your UID can call the OS keychain on your behalf. The OS will prompt the first time per app, but a sufficiently privileged attacker bypasses that.
- A recovered, unencrypted disk. The OS keychain protects entries when the keychain is locked, but if your home directory was decrypted at the time of compromise the audit log + session history sit in plaintext.
Disk encryption + a strong login password + not running random binaries closes both of those.