Encrypted Secrets Management
Relevant source files
The following files were used as context for generating this wiki page:
Encrypted Secrets Management in Cogmo is a foundational security system designed to protect sensitive credentials and data at rest. It ensures that API keys (Anthropic, OpenAI, Telegram), user-provided credentials, and application-level data like S3-stored attachments are never stored in plaintext. The system operates on a "zero-plaintext" principle where the database and object storage only ever see ciphertext.
The architecture relies on a master key provided at runtime to derive purpose-specific keys using HKDF, ensuring domain separation. This means that compromising a derived key for one subsystem (e.g., S3 storage) does not compromise others (e.g., database secrets).
Sources: design/infrastructure.md:46-51, DEPLOYMENT.md:120-125
Key Derivation and Encryption Scheme
Cogmo uses AES-256-GCM for encryption and HKDF-SHA256 for key derivation. The encryption is implemented using the @noble/ciphers and @noble/hashes libraries, chosen for their stateless APIs and security audits.
Master Key and Derivation
A 32-byte master key is provided via the COGMO_MASTER_KEY environment variable. This key is used to derive purpose-scoped keys with specific "info" strings to ensure that different parts of the system use independent cryptographic keys.
The derivation process uses a fixed salt derived from the string "cogmo" and versioned purpose strings to allow for future key rotation without changing the master key.
Sources: src/secrets/encryption.ts:18-35, design/infrastructure.md:65-79
Encryption Primitives
Encryption follows the standard GCM convention where a unique 12-byte nonce is generated for every encryption operation, and the authentication tag is appended to the ciphertext.
| Component | Specification |
|---|---|
| Cipher | AES-256-GCM |
| Hash | SHA-256 |
| Nonce Length | 12 Bytes |
| Key Length | 32 Bytes (256 bits) |
| Auth Tag | Appended to ciphertext |
Sources: src/secrets/encryption.ts:11-16, design/infrastructure.md:65-70
Secrets at Rest (Database)
Application-level credentials such as LLM provider keys and channel bot tokens are stored in a dedicated secrets table. These secrets are resolved at runtime by adapters and services, meaning the application logic rarely handles plaintext credentials directly.
Data Model: secrets Table
The schema is designed to track not only the encrypted payload but also the health and provenance of each secret.
| Field | Type | Description |
|---|---|---|
id | UUID v7 | Primary key. |
name | TEXT | Unique identifier (e.g., 'anthropic_api_key'). |
ciphertext | TEXT | Base64-encoded encrypted value. |
nonce | TEXT | Base64-encoded random nonce used for encryption. |
description | TEXT | Human-readable purpose. |
validated_at | TIMESTAMPTZ | Timestamp of last successful provider ping. |
Sources: design/infrastructure.md:53-63
Secret Retrieval Flow
When a channel adapter (like Telegram) starts, it does not receive the raw token. Instead, it receives a reference, which the secrets store resolves using the derived secrets key.
Object Storage Encryption (S3)
Cogmo supports client-side encryption for files stored in S3/R2 buckets. When S3_CLIENT_ENCRYPT=true is set, Cogmo encrypts both conversation attachments and workspace files before uploading them.
The Blob Envelope Format
Encrypted files use a custom binary envelope format to ensure they can be identified and decrypted safely even if the encryption flag is toggled or updated.
| Offset | Size | Name | Value / Description |
|---|---|---|---|
| 0 | 4B | Magic | 0xC0 0x6C 0x6D 0x6F (Unique Cogmo prefix) |
| 4 | 2B | Version | 0x00 0x01 (Big-endian version 1) |
| 6 | 12B | Nonce | Random nonce for GCM. |
| 18 | Variable | Payload | Ciphertext + GCM Auth Tag. |
Sources: src/secrets/blob-envelope.test.ts:21-27, changelog.d/2026-05-09-s3-client-encryption.md:12-18
Transparent Fallback
The system implementers prioritized availability by allowing transparent fallbacks. When reading an object, Cogmo checks for the magic 4-byte prefix. If absent, it treats the data as plaintext, allowing "legacy" files to remain readable after encryption is enabled.
Sources: changelog.d/2026-05-09-s3-client-encryption.md:5-10
Operational Security and Deployment
Cogmo provides subcommands to manage the root of trust and initial configuration.
Master Key Generation
The gen-key subcommand produces a fresh 32-byte base64 string.
docker run --rm ghcr.io/iskhakovt/cogmo:latest gen-key
Sources: DEPLOYMENT.md:204-209
Configuration via Environment Variables
To prevent sensitive keys from appearing in process lists or logs, Cogmo supports the _FILE convention for Docker secrets.
COGMO_MASTER_KEYorCOGMO_MASTER_KEY_FILE: The root encryption key.DATABASE_URLorDATABASE_URL_FILE: Connection string for Postgres.S3_CLIENT_ENCRYPT: Boolean flag to enable/disable object storage encryption.
Sources: design/infrastructure.md:86-90, DEPLOYMENT.md:135-145
The secrets management system provides a robust security layer that separates the master key from operational data. By utilizing industry-standard AES-256-GCM and purpose-isolated HKDF derivation, Cogmo protects user credentials and personal data against unauthorized access at the storage layer while maintaining operational flexibility through features like transparent S3 encryption fallbacks.