Skip to main content

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.

OSBackendWhere to inspect
macOSKeychain Services (login keychain)Keychain Access app → login → search kaneaz-harness
WindowsCredential ManagerCredential ManagerWindows Credentials → look for kaneaz-harness:*
LinuxSecret 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.

LocatorWhat it isCreated when
provider:<id>:api_keyAPI key for a configured providerYou add a provider
provider:<id>:aws_access_key / …:aws_secret_key / …:aws_session_tokenBedrock IAM credentials when configuredBedrock provider with long-term keys or assume-role
mcp:<id>:env:<KEY>An env var typed into an MCP server's environment blockYou save an MCP server with envs
mcp:<id>:oauth:access_token / …:refresh_tokenOAuth tokens for MCP servers that use the Kenaz credential resolverOAuth grant on first use
audit:signing_keyEd25519 private key that signs exported audit bundlesFirst launch
update:keypairLocal update verification keypairFirst 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:

  1. UI accepts plaintext (Provider editor, MCP env block, OAuth callback).
  2. Plaintext is written to the OS keychain via the platform-native API.
  3. The plaintext buffer is zeroed in memory.
  4. 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:

  1. Export your providers.json, mcp.json, and other Kenaz configs from $XDG_CONFIG_HOME/kaneaz-harness/ (these contain no secrets, just locators and structure).
  2. On the new machine, drop them into the same directory.
  3. Open Kenaz; each provider/MCP shows up greyed out as "missing credential."
  4. Click each one → re-paste. Done.

Threat model boundaries

Kenaz's secret store is designed against:

  • Casual filesystem accesscat ~/.config/kaneaz-harness/providers.json reveals 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.