Credential management
How Ethen manages API keys and provider credentials across the Gateway, Desktop, and local runtimes.
This page documents how Ethen handles API keys, provider credentials, and authentication secrets across product surfaces.
Credential stores
Ethen uses a provider credential store interface (ProviderCredentialStore) with two implementations:
| Implementation | Backing storage | Use case |
|---|---|---|
Desktop (safeStorage) | Electron safeStorage.encryptString/decryptString via IPC | Desktop app local model runtime |
| Web (env-var) | process.env resolution | Gateway and web-mode operations |
Both implementations follow these security rules:
- No provider key is ever written to plaintext JSON settings.
- Credential references (used for UI display) never include the raw secret value.
- Renderer requests for secrets go through IPC or daemon boundary.
- Web mode continues to resolve keys from environment variables only —
setSecretanddeleteSecretare no-ops.
Known provider credentials
The following provider credentials are recognised by the credential store:
| Provider | Environment variable |
|---|---|
| OpenAI | OPENAI_API_KEY |
| Anthropic | ANTHROPIC_API_KEY |
| DeepSeek | DEEPSEEK_API_KEY |
| OpenAI-compatible | ETHEN_OPENAI_COMPATIBLE_API_KEY |
GOOGLE_API_KEY | |
| Groq | GROQ_API_KEY |
| Mistral | MISTRAL_API_KEY |
| Cohere | COHERE_API_KEY |
| Together | TOGETHER_API_KEY |
| Fireworks | FIREWORKS_API_KEY |
| Perplexity | PERPLEXITY_API_KEY |
| xAI | XAI_API_KEY |
API key hashing
Gateway API keys are hashed using SHA-256 with a random salt before storage:
stored = "sha256:{salt}:{digest}"Verification uses constant-time comparison (crypto.timingSafeEqual) to prevent timing side-channel attacks. Keys that were never created or have been revoked cannot be verified through the hash alone.
Key fingerprinting
For identification in dashboards and logs, keys are fingerprinted without exposing the full value:
- Prefix: first 8 characters of the key beyond the environment prefix (
ethen_live_orethen_test_). - Suffix: last 6 characters of the key.
- Environment prefix:
ethen_live_for production keys,ethen_test_for test keys.
The raw key is never displayed after creation.
Secret redaction
Before any content is stored, displayed, or exported, the centralised redaction layer scans for:
- Well-known API key formats (OpenAI, Anthropic, AWS, SendGrid, Firebase, etc.)
- Generic
sk_/pk_prefixed secrets - Sensitive metadata field names (secrets, tokens, keys, passwords, credentials)
Redacted content replaces matched values with placeholders such as [REDACTED_API_KEY] or [REDACTED_OPENAI_KEY].
Desktop credential store availability
The Desktop safeStorage-backed credential store is unavailable in:
- Headless or test environments where Electron APIs are not loaded.
- Environments where
safeStorage.isEncryptionAvailable()returnsfalse.
In these environments, Desktop mode falls back to environment variable resolution. The isAvailable() method on the store interface can be queried at runtime.
Managed vault (Connected Apps)
OAuth grants and connector secrets for Connected Apps live in the managed vault, not in the stores above:
- The vault service is the only interface that may hold secret values. Production adapters are backed by a managed KMS/vault; database rows hold an opaque
externalRef, never the value. - Flow grant secrets resolve to a sealed credential handle reachable only through
reveal(); logs, errors, caches, and telemetry can only ever see redacted handles. - Secret kinds:
provider,connector,webhook,desktop,oauth_client. Statuses:staged,active,superseded,revoked. - Every vault touch emits an audit event (created, read, rotated, revoked) with actor, purpose, reference, and version.