Skip to main content

Security and isolation of the memory

Authentication always on​

EngineMechanismVerified safeguards
Mem0AUTH_DISABLED=false; admin key X-API-Key, user API keys (m0sk_...) or JWTcall without a key or with a wrong key: 401; public registration closed (403), the first administrator being created by the launcher before the API listens; a revoked key is refused
CogneeREQUIRE_AUTHENTICATION and ENABLE_BACKEND_ACCESS_CONTROL set to true; key X-Api-Key stored as a salted hashcall without a key: 401; the upstream account default_user@example.com does not exist; public registration refused (403) except with the service key; cloud sync refused (403)

These safeguards are proven by test_mem0_real.py and test_cognee_real.py. In Cognee the URL ingestion (allow_url_ingestion) and the Cypher queries (allow_cypher) are off by default, and a local file outside the data root is refused (415). The MCP server of Cognee has no authentication of its own: it listens on 127.0.0.1 only.

Telemetry off and no outbound traffic​

Mem0 runs with MEM0_TELEMETRY=false (the launcher refuses any other value). Cognee runs with TELEMETRY_DISABLED, RUNTIME__DLTHUB_TELEMETRY=false, HF_HUB_OFFLINE, HF_HUB_DISABLE_TELEMETRY, TRANSFORMERS_OFFLINE and DO_NOT_TRACK. The real tests send every outbound HTTP(S) of the engines to a recording proxy that must stay unused: it stayed unused.

Secrets​

  • Generated and sealed by the Manager at installation: for Mem0 admin_api_key, jwt_secret, admin_password; for Cognee admin_password, service_api_key, jwt_secret, reset_password_secret, verification_secret, api_key_salt.
  • Never on the command line nor in the logs: the tests check that no value appears in the arguments nor in the API journal, and the functional test masks the key.
  • Rotation: a new value and a restart for the API keys; changing a JWT secret ends every session; changing api_key_salt invalidates every Cognee API key except the service one.
  • In Navin Enterprise the keys of the platform instances come from the sensitive environment file (env://EAI_CRED_MEMORY_MEM0_API_KEY, env://EAI_CRED_MEMORY_COGNEE_API_KEY); the key of a tenant on a shared instance is an OpenBao reference (openbao://...). They are resolved server side, never returned nor logged.

Derived context and scope mapping​

The context of an operation (tenant, organization, project, user, agent, session, scope, team) is derived from the authenticated identity and the agent registry, never from parameters sent by an agent. A controlled mapping turns it into engine identifiers:

EngineIdentifiers used
Mem0user_id, agent_id, run_id and the metadata (navin_ns and the scope fields)
Cogneethe dataset name

Each identifier carries an opaque prefix, an HMAC of the instance, the tenant and the project, that cannot be guessed.

Isolation guarantee and refusal​

GuaranteeWhen
logicalidentifiers and prefix enforced by Navin only: any shared Mem0 instance (its keys do not scope the memories), a shared Cognee instance without a user of the tenant
backendseparation enforced by the engine: builtin (PostgreSQL row level security), Cognee with access control and a Cognee user of the tenant
dedicated_instanceinstance installed by the Manager for this tenant only and declared with its tenant_id

The agent policy sets required_isolation. When the chosen instance guarantees less, the operation is refused with memory_isolation_unsatisfied (HTTP 409): "a dedicated instance installed by the Navin Manager is required". For a bank, require dedicated_instance and install one Mem0 or Cognee instance per tenant. The separation of two users in one Cognee instance is proven by test_cognee_real.py: one neither sees, reads nor searches the datasets of the other until a read permission is given.

Authorization, policies and audit​

  • OpenFGA: the caller must be the agent itself or hold a relation on it (can_invoke for memories and knowledge, viewer or editor for the policy).
  • OPA: each write goes through the decision memory.write, each read through memory.search, before the engine call.
  • Roles: declaring or removing an instance needs platform_admin; setting the key of a tenant tenant_admin.
  • Audit: each operation writes an event (operation, context, engine, decision, result), never the content of the memories. A refusal or an engine failure also writes a deny or failure event.

Recalled memories and secrets​

  • Recalled memories are untrusted data, never instructions. Their content goes through the prompt injection screen of the gateway (a blocked item is dropped), then each item is wrapped in the untrusted data markers and given to the Context Manager as a memory segment. Permissions are checked before anything is given to the LLM.
  • Secrets, passwords, tokens and keys are never memorized: the DLP detects them and the write is refused with memory_secret_refused (HTTP 422). Personal data is refused when the policy sets allow_personal_data to false.