Sécurité et isolation de la mémoire
Authentification toujours active
| Moteur | Mécanisme | Garde-fous vérifiés |
|---|---|---|
| Mem0 | AUTH_DISABLED=false ; clé d'administration X-API-Key, clés d'API des utilisateurs (m0sk_...) ou JWT | appel sans clé ou avec une mauvaise clé : 401 ; inscription publique fermée (403), le premier administrateur étant créé par le lanceur avant que l'API écoute ; une clé révoquée est refusée |
| Cognee | REQUIRE_AUTHENTICATION et ENABLE_BACKEND_ACCESS_CONTROL à true ; clé X-Api-Key stockée sous forme d'empreinte salée | appel sans clé : 401 ; le compte amont default_user@example.com n'existe pas ; inscription publique refusée (403) sauf avec la clé de service ; synchronisation cloud refusée (403) |
Ces garde-fous sont prouvés par test_mem0_real.py et test_cognee_real.py. Chez Cognee, l'ingestion par URL
(allow_url_ingestion) et les requêtes Cypher (allow_cypher) sont désactivées par défaut, et un fichier local hors
de la racine des données est refusé (415). Le serveur MCP de Cognee n'a pas d'authentification propre : il n'écoute
que sur 127.0.0.1.
Télémétrie coupée et aucune sortie
Mem0 tourne avec MEM0_TELEMETRY=false (le lanceur refuse une autre valeur). Cognee tourne avec
TELEMETRY_DISABLED, RUNTIME__DLTHUB_TELEMETRY=false, HF_HUB_OFFLINE, HF_HUB_DISABLE_TELEMETRY,
TRANSFORMERS_OFFLINE et DO_NOT_TRACK. Les tests réels font passer toute sortie HTTP(S) des moteurs par un proxy
d'enregistrement qui doit rester inutilisé : il l'est resté.
Secrets
- Générés et scellés par le Manager à l'installation : pour Mem0
admin_api_key,jwt_secret,admin_password; pour Cogneeadmin_password,service_api_key,jwt_secret,reset_password_secret,verification_secret,api_key_salt. - Jamais dans la ligne de commande ni dans les journaux : les tests vérifient qu'aucune valeur n'apparaît dans les arguments ni dans le journal de l'API, et le test fonctionnel masque la clé.
- Renouvellement : une nouvelle valeur et un redémarrage pour les clés d'API ; changer un secret JWT ferme toutes
les sessions ; changer
api_key_saltinvalide toutes les clés d'API de Cognee sauf celle de service. - Dans Navin Enterprise, les clés des instances de plateforme arrivent par le fichier d'environnement sensible
(
env://EAI_CRED_MEMORY_MEM0_API_KEY,env://EAI_CRED_MEMORY_COGNEE_API_KEY) ; la clé d'un tenant sur une instance partagée est une référence OpenBao (openbao://...). Elles sont résolues côté serveur, jamais renvoyées ni journalisées.
Contexte dérivé et correspondance des portées
Le contexte d'une opération (tenant, organisation, projet, utilisateur, agent, session, portée, équipe) est dérivé de l'identité authentifiée et du registre des agents, jamais des paramètres envoyés par un agent. Une correspondance contrôlée le traduit en identifiants du moteur :
| Moteur | Identifiants utilisés |
|---|---|
| Mem0 | user_id, agent_id, run_id et les métadonnées (navin_ns et les champs de la portée) |
| Cognee | le nom du jeu de données |
Chaque identifiant porte un préfixe opaque, une HMAC de l'instance, du tenant et du projet, qu'on ne peut pas deviner.
Garantie d'isolation et refus
| Garantie | Quand |
|---|---|
logical | identifiants et préfixe imposés par Navin seul : toute instance Mem0 partagée (ses clés ne limitent pas les mémoires), une instance Cognee partagée sans utilisateur propre au tenant |
backend | séparation imposée par le moteur : builtin (sécurité au niveau des lignes de PostgreSQL), Cognee avec contrôle d'accès et un utilisateur Cognee propre au tenant |
dedicated_instance | instance installée par le Manager pour ce seul tenant et déclarée avec son tenant_id |
La politique de l'agent fixe required_isolation. Quand l'instance choisie garantit moins, l'opération est refusée
avec memory_isolation_unsatisfied (HTTP 409) : « une instance dédiée installée par le Navin Manager est
nécessaire ». Pour une banque, exiger dedicated_instance et installer une instance Mem0 ou Cognee par tenant. La
séparation de deux utilisateurs dans une même instance Cognee est prouvée par test_cognee_real.py : l'un ne voit,
ne lit ni ne cherche les jeux de l'autre tant qu'une permission de lecture n'est pas donnée.
Autorisations, politiques et audit
- OpenFGA : l'appelant doit être l'agent lui-même ou détenir une relation sur lui (
can_invokepour les mémoires et les connaissances,vieweroueditorpour la politique). - OPA : chaque écriture passe la décision
memory.write, chaque lecturememory.search, avant l'appel au moteur. - Rôles : déclarer ou retirer une instance demande
platform_admin; déposer la clé d'un tenanttenant_admin. - Audit : chaque opération produit un événement (opération, contexte, moteur, décision, résultat), jamais le
contenu des mémoires. Un refus ou une panne du moteur produit aussi un événement
denyoufailure.
Mémoires restituées et secrets
- Les mémoires restituées sont des données non fiables, jamais des instructions. Leur contenu passe le filtre
d'injection de prompt de la passerelle (un élément bloqué est écarté), puis chaque élément est entouré des marqueurs
de données non fiables et donné au Context Manager comme segment
memory. Les permissions sont contrôlées avant toute restitution au LLM. - Les secrets, mots de passe, jetons et clés ne sont jamais mémorisés : la DLP les détecte et l'écriture est refusée
avec
memory_secret_refused(HTTP 422). Les données personnelles sont refusées quand la politique poseallow_personal_dataàfalse.