# Secrets and Authentication Security Model ## Stored credential policy Conductor stores REST credential values in SQLite encrypted with AES-256-GCM. A persistent 32-byte master key is supplied as `CONDUCTOR_SECRET_KEY`, encoded as base64 or 64 hexadecimal characters. The key is never stored in SQLite, project JSON, frontend state, browser responses, execution history, or source control. Canonical project actions identify credentials by an opaque `secretReferenceId`. After authorization, the backend resolves the credential while constructing the upstream request. Destination and redirect policy must pass before that request is transmitted; the browser never receives the credential value. ## Access boundaries - Administrators can create, replace, list, and delete stored-credential metadata through **Actions & Bindings → Secrets**. - Administrators cannot retrieve an existing credential value; replacement requires the complete new value. - Users and anonymous visitors cannot list secret metadata or access authoring APIs. - Public applications may contain only anonymous actions and cannot use stored credentials. - Restricted published applications may use stored credentials, but the browser submits only runtime values to an action already fixed in the server-owned snapshot. - Host operators with both the database and encryption key are inside the trusted recovery boundary and could decrypt credentials. Deletion is blocked while a saved project action refers to the credential. Secret names and authentication types are non-secret metadata, but should still avoid embedding customer or credential values. ## Stored credential shapes - `basicAuth`: username and password - `bearerToken`: token - `apiKeyHeader`: header name and API-key value - `apiKeyQueryParameter`: query-parameter name and API-key value List and lookup responses contain only ID, name, authentication type, and timestamps. ## Key and session lifecycle - Generate `CONDUCTOR_SECRET_KEY` once with `openssl rand -hex 32` and preserve it across restarts, upgrades, and restores. - Generate `CONDUCTOR_SESSION_KEY` independently with `openssl rand -hex 32`. It protects sessions; changing it signs everyone out. - Production startup fails if the encryption key does not encode exactly 32 bytes or the session key contains fewer than 32 bytes. - Losing or changing `CONDUCTOR_SECRET_KEY` makes existing stored credentials unrecoverable. - Online key rotation and credential re-encryption are not implemented in v1.0.0. - Never commit `.env`, paste key values into tickets, or include them in terminal recordings and screenshots. The public installation procedure creates `.env` with mode `0600`. The backup tool includes that file because the database alone is not a complete recovery set. Treat every backup archive as a credential-bearing secret, keep an off-host copy, and restore the archive as one unit. Do not combine a database with keys from another installation. ## Threat assumptions Encryption at rest protects against disclosure of SQLite alone. It does not protect against compromise of the running backend process, a hostile host administrator, memory inspection, a compromised REST destination, or an attacker who obtains both the database and master key. Authentication injection, URL sanitization, and error/history redaction occur server-side. Query-string API keys receive the same encrypted storage but remain inherently more likely to be exposed by an upstream service; prefer header-based authentication when the destination supports it. See [Authorization and Publishing Security](AUTHORIZATION_AND_PUBLISHING_SECURITY.md), [Proxy Security](PROXY_SECURITY.md), and [Production Operations](OPERATIONS.md) for the surrounding trust and recovery model.