Fini le harcèlement du keychain : le chiffrement opt-in via le keychain de l'OS pour les secrets stockés


Lundi matin, vous ouvrez l’application de bureau Hermes, et au lieu de votre liste de chats vous obtenez une boîte de dialogue macOS : « Hermes veut accéder à votre keychain. Saisissez votre mot de passe pour autoriser. » Vous le tapez, l’application se charge. Mardi : même dialogue. À chaque lancement, pour toujours — parce que les secrets de l’application étaient chiffrés avec une clé déposée dans le keychain de connexion, et que votre keychain était verrouillé, manquant ou corrompu. C’est le genre de harcèlement qui donne envie de jeter la machine par la fenêtre. Hermes v0.20.6 (commit 6a6e16fa5d) corrige cela à la racine : le chiffrement des secrets stockés via le keychain est désormais un opt-in explicite, et le chemin par défaut n’appelle jamais le keychain du tout.

Le changement vise les secrets stockés par le bureau : tokens de gateway distant, en-têtes Cloudflare Access et ensembles de tokens OAuth natifs. Avant, le safeStorage d’Electron déposait une clé par application (« Hermes Key ») dans le keychain de connexion de macOS, et tout accès à safeStorage — même la vérification « le chiffrement est-il disponible ? » — pouvait déclencher une boîte de dialogue bloquante sur les machines avec un keychain par défaut verrouillé ou corrompu. C’était un défaut inacceptable pour une application de chat, si bien que le comportement a été inversé : le chiffrement est désormais opt-in, le stockage en clair est le défaut, et une migration en un seul passage nettoie après l’ancien comportement.

Ce qui a changé

La politique est définie dans un module autonome (electron/secret-storage-policy.ts) — volontairement exempt de import 'electron' pour se tester proprement en unités — avec trois propriétés :

  • Option DÉSACTIVÉE (défaut) : les secrets sont écrits avec l’encodage 'plain' et aucune API safeStorage n’est jamais appelée — y compris isEncryptionAvailable(), qui touche elle-même le keychain. Pas de keychain, pas de dialogue, pas d’invite.
  • Option ACTIVÉE : l’ancien comportement — chiffrement strict par safeStorage, échec bruyant lorsque le keychain est indisponible, et une boîte de dialogue de confirmation en clair à chaque sauvegarde comme porte de sortie.
  • Migration en un seul passage : les blobs hérités écrits avant l’existence de l’option sont encodés par safeStorage sur disque. Avec l’option désactivée, Hermes tente un passage de migration (déchiffrer → réécrire en clair). Le passage est enregistré dans le même fichier de réglages, qu’il réussisse ou non, si bien qu’un keychain cassé coûte au plus une invite au premier lancement après la mise à jour — jamais une par lancement.

L’option on utilise une coercition stricte === true : une valeur véridique mais non vraie ne doit pas activer silencieusement les invites de keychain (en miroir de la règle de coercition allowPlainText dans hardening.ts). Le fichier de politique se trouve à secure-token-storage.json.

Comment l’utiliser

Bureau (recommandé) : ouvrez Réglages → Gateway, trouvez l’option de stockage sécurisé/keychain et activez-la. Activer l’option ré-encode chaque magasin de secrets stocké sur place — connection.json v1, connections.json v2 et native-oauth-tokens.json — et la spécification au repos couvre les deux postures : contrat inchangé pour les opt-in, sauvegardes par défaut sans stockage sécurisé, bits de propriétaire seul, et aller-retour de redémarrage.

Le détail de migration qui vaut la peine d’être connu : si vous venez d’une version plus ancienne, le premier lancement après la mise à jour avec le réglage par défaut (désactivé) tente la migration en un seul passage — déchiffrer les blobs safeStorage existants en fichiers 0600 en clair. Les blobs indéchiffrables (un keychain mort, par exemple) sont conservés sur disque mais lus comme absents ensuite, classés en « drop », si bien qu’un keychain mort invite au plus une fois. Sous Linux, le backend de keychain sous-jacent est configurable : desktop.password_store accepte auto (détecter le keychain de session — KWallet via les variables d’environnement de session KDE, GNOME Keyring / tout provider org.freedesktop.secrets comme KeePassXC via D-Bus) ou un backend forcé (gnome-libsecret, kwallet, kwallet5, kwallet6) ; basic signifie un stockage non chiffré. Une variable d’environnement explicite HERMES_DESKTOP_PASSWORD_STORE l’emporte toujours sur la configuration.

Ce qui ne change pas

  • Les machines opt-in conservent le contrat complet : chiffrement strict par safeStorage, échec bruyant lorsque le keychain est indisponible.
  • Les permissions de fichiers propriétaire seul sur les fichiers de repli en clair (0600) maintiennent la posture « non chiffré au repos » raisonnable : lisibles uniquement par votre utilisateur.
  • Les secrets restent des secrets. Le changement porte sur l’endroit où vit la clé de chiffrement (keychain de l’OS vs fichiers en clair propriétaire seul), pas sur l’exposition des tokens dans les logs ou le contenu visible par le modèle — la machinerie de rédaction existante (security.redact_secrets) est intacte.

Quand opter pour le chiffrement

  • Optez pour si vous voulez un chiffrement au repos au niveau de l’OS et que votre keychain est sain — la posture standard pour les laptops, les machines partagées ou les environnements soucieux de conformité.
  • Laissez-le désactivé si votre keychain est verrouillé/manquant/corrompu (la population de la boîte de dialogue), si vous préférez ne pas avoir une clé par application assise dans le keychain de connexion, ou si l’invite à chaque lancement vous rendait fou. Le chemin par défaut est désormais sans invite par conception.

Le tableau d’ensemble

Ce changement fait partie du thème fiabilité de la v0.20.6 : la même fenêtre qui a fait de la mise en cache de la recherche web et de la compression lean-tail des défauts a aussi empêché le programme de mise à jour de tuer les gateways en cascade (voir notre guide de mise à niveau gracieuse). Le stockage des secrets était la dernière chose du bureau qui pouvait bloquer votre matinée avec une boîte de dialogue de mot de passe — désormais c’est opt-in, silencieux et réversible. Pour le récapitulatif complet de la version, voir les notes de version v0.20.6.

Une seule option. Fini le « Hermes veut accéder à votre keychain » quotidien — sauf si vous voulez le chiffrement, auquel cas il est toujours là, à un interrupteur.