Skip to content

Latest commit

 

History

History
232 lines (167 loc) · 10.7 KB

File metadata and controls

232 lines (167 loc) · 10.7 KB

Security & Privacy Model

Last updated: June 2026 · Mnemosyne v3.7.0

You are solely responsible for the content stored in Mnemosyne. Mnemosyne Sync supports optional client-side encryption. When disabled, memory content travels over TLS and is stored according to your infrastructure's security settings.


Philosophy

Mnemosyne is built on three security principles:

  1. User sovereignty — You own your data. Mnemosyne has no telemetry, no tracking, no cloud dependency. The database file is yours.
  2. Privacy by design — The default configuration stores everything locally. No data ever leaves your machine unless you explicitly enable sync.
  3. Minimal trust in remote infrastructure — When sync is enabled, optional client-side encryption ensures that even the remote server cannot read your memory contents. The remote side sees only routing metadata (timestamps, event IDs, device IDs).

Data at Rest

Mnemosyne stores all data in a single SQLite file (default: ~/.hermes/mnemosyne/data/mnemosyne.db).

Layer Data Security
Working memory Recent agent context, preferences, facts Plaintext in SQLite. File permissions control OS-level access.
Episodic memory Consolidated long-term memories, vector embeddings Same as working memory. Embeddings are mathematical vectors, not reversible to original text.
TripleStore Temporal knowledge graph (subject-predicate-object triples) Same as working memory.
Config API keys, endpoints, encryption settings Stored in environment variables or config.yaml. Never logged or transmitted.

Recommendations for data at rest:

  • Set restrictive file permissions: chmod 600 ~/.hermes/mnemosyne/data/mnemosyne.db
  • Use full-disk encryption (LUKS, FileVault, BitLocker)
  • On shared machines, use memory banks for isolation: mnemosyne --bank <name>

Data in Transit (Sync)

When mnemosyne sync is enabled, memory content travels between instances over HTTP/HTTPS.

Without Client-Side Encryption

What the remote server sees Example
Memory content (plaintext) "User prefers dark mode"
Importance scores 0.9
Memory type / source "preference", "cli"
Event metadata event_id, timestamp, device_id, operation (CREATE/UPDATE/DELETE)
Vector embeddings Opaque binary data (not reversible to text, but could be used for similarity analysis)

Protection: TLS encryption between instances (recommended). Behind a reverse proxy (Caddy, Nginx, Traefik) with automatic HTTPS.

With Client-Side Encryption (--encrypt)

What the remote server sees Example
Memory content Encrypted::<base64 ciphertext> (unreadable without the key)
Importance scores Encrypted alongside content
Memory type / source Encrypted alongside content
Unencrypted metadata (required for routing) event_id, timestamp, device_id, operation
Vector embeddings Encrypted as part of payload

Protection: Authenticated encryption via cryptography.fernet.Fernet (AES-128-CBC) or nacl.secret.SecretBox (XSalsa20-Poly1305). The remote server cannot decrypt any payload content. See Encryption in Mnemosyne Sync below.


Encryption in Mnemosyne Sync

Overview

Client-side encryption is optional but first-class. When enabled, memory payloads are encrypted on the sending side before transmission and decrypted on the receiving side after receipt. The remote server (including the Mnemosyne sync endpoint) never has access to the encryption key.

How It Works

┌─────────────────────┐           ┌─────────────────────┐
│   Local Instance    │           │   Remote Instance   │
│                     │           │                     │
│  1. Encrypt payload │  ──────►  │  3. Store encrypted │
│     with local key  │  (TLS)   │     payload as-is   │
│                     │           │                     │
│  4. Request changes │  ◄────── │  2. Return encrypted │
│  5. Decrypt payload │  (TLS)   │     payloads         │
│     with local key  │           │                     │
└─────────────────────┘           └─────────────────────┘

The encryption key never leaves the local instance. The remote instance stores and serves encrypted payloads without ever decrypting them.

Key Sources

Source Configuration Security Level Where Supported
Environment variable MNEMOSYNE_SYNC_KEY=<base64-key> Medium (env may be logged) Core, Hermes adapter
File path --encrypt /path/to/keyfile Medium (file perms) CLI, Hermes adapter
Raw key string --encrypt <base64-key> Low (visible in ps) CLI, Hermes adapter
OS keyring MNEMOSYNE_SYNC_KEY_SOURCE=keyring High (OS keychain) Hermes adapter only
Derived from passphrase MNEMOSYNE_SYNC_PASSPHRASE=<phrase> Medium (Argon2id derived) Hermes adapter only

Core SyncEncryption.from_config() reads from $MNEMOSYNE_SYNC_KEY, a file path, or a raw key string. The Hermes sync adapter adds keyring and passphrase support.

Key Derivation

SyncEncryption.derive_key() converts a passphrase to a 32-byte key:

  • Default: PBKDF2-HMAC-SHA256 with 600,000 iterations
  • If argon2-cffi is installed: Argon2id (memory-hard, recommended)

Note: from_config() does not currently call derive_key() — passphrases require the Hermes sync adapter or manual key derivation.

# Generate a random key
mnemosyne sync generate-key
# Output: 7A8B3C... (base64, 32 bytes)

# Use with CLI
mnemosyne sync --encrypt MNEMOSYNE_SYNC_KEY=7A8B3C...
mnemosyne sync --encrypt /path/to/keyfile

# Enable in Hermes (config.yaml)
mnemosyne:
  sync:
    key: "7A8B3C..."
    encrypt: true

What Gets Encrypted

The payload field of each sync event is encrypted. Payload includes:

  • Memory content text
  • importance score
  • source field
  • metadata_json (if present)
  • memory_type / veracity fields
  • Vector embeddings (binary_vector)

What Stays Unencrypted (Metadata)

These fields are always sent in plaintext for routing and conflict resolution:

  • event_id — Unique event identifier (UUID)
  • memory_id — References the memory row
  • operation — CREATE / UPDATE / DELETE / CONSOLIDATE
  • timestamp — ISO 8601 timestamp
  • device_id — Which device originated the event
  • parent_event_ids — Causality chain for conflict detection

This means an adversary with access to the remote sync server can learn:

  • How many memory events are being synced
  • When they occurred
  • Which events are related to each other
  • Which devices are syncing

They cannot learn the content or meaning of those memories when encryption is enabled.


Liability & Disclaimer

Mnemosyne is provided "as is", without warranty of any kind.

You are solely responsible for:

  • The content you store in Mnemosyne
  • Securing your database file (file permissions, disk encryption)
  • Securing your sync channel (TLS certificates, network configuration)
  • Managing your encryption keys (key rotation, backup, loss prevention)
  • Compliance with applicable laws regarding data storage and transfer

Mnemosyne Sync supports optional client-side encryption. When disabled, memory content travels over TLS and is stored according to your infrastructure's security settings. Even with encryption enabled, metadata (event counts, timestamps, device IDs) is visible to the remote server for routing purposes.

See the LICENSE file for the full terms.


Comparison with Alternatives

System Data at Rest Data in Transit Client-Side Encryption Self-Hostable
Mnemosyne Local SQLite (file permissions) TLS + optional client-side encryption Yes (sync, Fernet/XSalsa20-Poly1305) Yes
Mem0 Qdrant/PostgreSQL TLS No Optional
Zep BYOK (data at rest) TLS BYOK only (server-managed) Yes
Letta PostgreSQL TLS No Yes
Honcho PostgreSQL TLS No Yes
Supermemory Cloud (SaaS) TLS No Enterprise only
Hindsight Local SQLite TLS No Yes

Mnemosyne is the only memory system with client-side encryption of sync payloads as a core feature, not an afterthought. Zep offers BYOK for data-at-rest but manages the key server-side — Mnemosyne keeps the key entirely client-side.


Threat Model

In Scope

Threat Mitigation
Remote server compromise → memory content exposure Client-side encryption renders payloads unreadable
TLS interception (MITM) TLS with certificate validation
Unauthorized sync access API key / JWT authentication on sync endpoints
Replay attacks Unique event IDs + timestamp validation
Sync of malicious content Destination-side content filtering via ignore_patterns

Out of Scope (v1)

Threat Rationale
Side-channel attacks on encryption timing Performance-sensitive sync makes constant-time hard. Use TLS for transit security.
Quantum cryptanalysis of Fernet/SecretBox Not a practical threat for memory content. Key rotation mitigates long-term risk.
Physical access to the database file OS-level controls (file permissions, disk encryption) are the user's responsibility
Denial of service on sync endpoint Self-hosted deployments manage their own rate limiting and firewall rules

Best Practices

  1. Always use HTTPS/TLS for sync connections. Never sync over plain HTTP outside a local network.
  2. Enable client-side encryption if syncing over the internet or to a shared/VPS instance.
  3. Rotate sync keys periodically (e.g., every 90 days).
  4. Back up your encryption keys separately from your Mnemosyne database. Losing the key means losing access to encrypted memories.
  5. Use environment-specific keys — separate keys for development, staging, and production.
  6. Monitor sync events with mnemosyne sync status --remote <url> to verify no unexpected sync activity.

Related