Skip to the content.

Compartment Security Model

Honest threat model. Read the “cannot protect against” section too - a security product that claims everything protects nothing.

Cryptography

Purpose Primitive
All encryption at rest XChaCha20-Poly1305 AEAD (libsodium via PyNaCl)
Key derivation Argon2id (t=3, m=64MiB, p=4; params stored in header)
Keyslots LUKS-style: random 256-bit master key wrapped per slot
Recovery 16 words from a 256-word list = 128 bits, own keyslot
Per-record keys wrapped by master key → crypto-shred on forget --shred
Signing (vaults + packs) Ed25519
Integrity AEAD tags everywhere + hash-chained audit log

No homemade crypto. AAD binds every ciphertext to its role and vault (payloads, journal entries by sequence number, keyslots, record bodies by record id) - ciphertexts cannot be transplanted between contexts.

What Compartment protects against

What Compartment CANNOT protect against

Unlock paths, ranked

  1. Boot-session credential (the default). compartment unlock wraps the master key with a key derived from the current boot’s kernel timestamp (plus uid + hostname) and stores it 0600 in ~/.compartment/session/. The vault then stays continuously usable - across processes, logouts, and logins, for weeks or months - and RELOCKS on any restart or power loss: the new boot’s derivation can never open the old wrap, and stale files are deleted on sight. This is deliberately a convenience credential - an attacker who can read it on the running machine could also read process RAM; once power is lost it is dead ciphertext. (A forensic caveat: the previous boot time may be recoverable from system logs, so on an unencrypted disk a stolen file pair is theoretically weaker than the passphrase. Use FileVault/FDE, which you should anyway.)
  2. macOS Keychain (compartment unlock --keychain, explicit opt-in): credential guarded by the OS keychain. Stronger against file theft than the session credential, but it SURVIVES REBOOTS - choose it only if that is what you want.
  3. COMPARTMENT_PASSPHRASE env var: for scripts/CI; visible to anything that can read the process environment.
  4. memory_unlock MCP tool: DISABLED by default. The passphrase would transit the agent’s context window and possibly the host’s logs/model provider. Enable only if you accept that (settings.unlock_tool_enabled in <vault>.config.json).

compartment lock and the memory_lock panic tool clear ALL stored credentials (session + keychain). Auto-lock drops the in-RAM key after auto_lock_minutes (default 30) idle; while a stored credential remains, the next operation silently re-opens - stored credentials represent standing user intent, ended by compartment lock or a reboot.

Two-factor interaction, stated honestly: with compartment 2fa enable, every credential-based unlock (passphrase paths 3-4 above, and any fresh compartment unlock) requires the keyfile too - that is enforced by the KDF. The session and keychain paths store the unwrapped MASTER key, so after one successful two-factor unlock they re-open the vault without re-presenting the keyfile, exactly as they skip the passphrase. That is the design (they encode standing intent on an already-trusted machine); if you want every single open to need both factors, run compartment unlock --once and don’t store a credential.

Multi-agent, one vault

Several agent processes (Hermes provider, Claude via MCP, the CLI) may share one vault: an advisory file lock serializes every journal append and save, and each process detects foreign writes (mtime/size) and reloads before proceeding - a stale writer gets a loud VaultStaleError, never silent corruption. Namespace ACLs are per-caller; --caller identity is declarative (see the hostile-host limitation above).

Reporting

Report vulnerabilities privately to the maintainer. No telemetry exists in this product; nothing phones home, so nothing can be recalled remotely.