Blog
Sécurité

Les couches de sécurité de Simmetric Chat : clés API, webhooks signés et DLP

Comment Simmetric Chat authentifie chaque requête, hache les clés API avec HMAC-SHA256, signe les webhooks et le Web Push, et rédige les données personnelles avec les filtres DLP.

Simmetric Team10 min de lecture08/09/2026

La sécurité est une pile, pas un interrupteur

Une plateforme de chat qui garde les documents de votre entreprise doit gagner la confiance par couches : comment les requêtes s'authentifient, comment l'accès programmatique est émis et conservé, comment les intégrations en arrière-plan prouvent leur légitimité, et ce qui arrive aux contenus sensibles quand ils traversent prompts et réponses. Simmetric Chat aborde chacun de ces aspects avec un mécanisme nommé, et v0.22 a fermé certaines des lacunes les plus subtiles - comparaisons de secrets timing-safe, login résistant à l'énumération et un moteur DLP qui couvre désormais aussi les identifiants européens structurés. Cet article parcourt la pile de la porte d'entrée vers l'intérieur.

Trois façons dont les requêtes s'authentifient

Chaque endpoint sous /api tombe dans l'un des trois régimes de credentials :

  • JWT Bearer (primaire). Les utilisateurs humains s'authentifient via l'endpoint de login ou d'inscription et reçoivent un JWT signé. Chaque token porte un claim jti vérifié contre une liste de révocation (optionnellement adossée à Redis), pour que la déconnexion ou la révocation administrative prennent effet immédiatement, pas à l'expiration. Les tokens invalides ou expirés reçoivent un 401 propre ; le middleware résout l'utilisateur avec rôles et permissions à chaque requête.
  • Clé API (`X-Api-Key`). L'accès programmatique - la surface de compte de service du widget et les clés créées par les utilisateurs via les endpoints API-key - utilise des clés préfixées vérifiées contre un digest HMAC, décrites ci-dessous.
  • Secret partagé du collector. Les appels service-à-service du collector d'ingestion portent X-Collector-Secret, comparé à temps constant avec une garde de longueur. C'était le dernier endroit où survivait une comparaison de secrets en clair sur le serveur, et v0.22 l'a fermé : les callbacks d'import d'archives utilisent désormais la même discipline crypto.timingSafeEqual que toute autre barrière de secrets.

Au-dessus de l'authentification se trouvent les gardes RBAC traitées dans un article séparé - contrôles de permissions, barrières admin et prévention IDOR sur l'accès aux workspaces et projets. L'authentification répond à « qui êtes-vous » ; le RBAC répond à « que pouvez-vous toucher ».

Clés API : HMAC-SHA256, chiffrées au repos

Une clé API est une credential porteur, donc la façon dont le serveur la conserve compte autant que la façon dont il la vérifie. Simmetric Chat émet des clés avec un préfixe sk- reconnaissable - familier aux écosystèmes d'outils que la plupart des développeurs utilisent déjà - et ne conserve jamais la clé elle-même. Au repos, chaque clé n'existe que comme digest HMAC-SHA256 calculé sous un secret dédié côté serveur, API_KEY_HMAC_SECRET :

text
sk-abc123… (émise une fois, montrée une fois à l'appelant)
 │  HMAC-SHA256(API_KEY_HMAC_SECRET, clé)
 ▼
key_hash conservé dans api_keys - la clé elle-même est irrécupérable

Le design a deux propriétés voulues :

  • Rotation découplée. API_KEY_HMAC_SECRET est indépendant de JWT_SECRET et de ENCRYPTION_KEY. Faire tourner la clé de signature des sessions n'invalide pas les clés API, et faire tourner la clé de chiffrement au repos ne casse pas la vérification des clés. Chaque secret a un seul travail.
  • Vérification à temps constant. La vérification est une recherche du digest HMAC à clé - O(1), sans limites take sur une analyse de candidats. C'est ce qui rend l'authentification par clé API assez bon marché pour tenir sur chaque requête dans un déploiement multi-instance.

Les utilisateurs gèrent leurs propres clés via les endpoints API-key : création à la demande, listage à la demande, révocation à la demande. La révocation supprime la capacité de reconstruire une credential valide ; le digest ne correspond plus à rien.

Webhooks signés et Web Push

Les intégrations sortantes doivent être vérifiables autant que celles entrantes.

Les webhooks sont signés avec HMAC-SHA256. Le serveur calcule une signature sur le payload en utilisant le secret du webhook, et votre service récepteur recalcule le digest avant de faire confiance au corps de l'événement. Un endpoint récepteur ne doit jamais faire confiance à un appelant qui prétend être Simmetric Chat - il peut le prouver, octet par octet, avec sa propre copie du secret. Un endpoint d'événements de test vous permet d'exercer un récepteur sans générer d'activité réelle sur la plateforme.

Le Web Push utilise le protocole VAPID pour les notifications navigateur. Le serveur détient une paire de clés VAPID ; la clé publique est exposée aux clients authentifiés via un endpoint système, les abonnements sont gérés via des endpoints explicites subscribe/unsubscribe, et les administrateurs peuvent envoyer un push de test pour vérifier la pipeline de bout en bout. Les deux canaux sont toujours actifs au palier Community - la signature et le push sont un comportement de base de la plateforme, pas une fonctionnalité enterprise.

Rate limiting à la frontière

Le rate limiting est stratifié par surface, avec les habituels en-têtes RateLimit-* émis sur les routes limitées :

  • Limiteur API global - 200 requêtes par minute par IP sur toutes les routes en production
  • Limiteur d'authentification - 10 requêtes par minute sur les endpoints d'écriture de l'authentification, la barrière la plus stricte parce que les endpoints de credentials sont les premières cibles des abus
  • Limiteur lead du widget - 3 requêtes par heure sur la capture des leads, parce qu'un formulaire public est là où l'abus automatisé se concentre
  • Limiteur de probe - 10 requêtes par minute sur les endpoints de probe de connectivité, pour que le test de l'assistant de configuration ne puisse pas être transformé en arme

Quand REDIS_URL est configuré, les compteurs vivent dans un store Redis partagé pour que les limites signifient la même chose sur chaque instance ; sinon chaque instance garde son propre store. Les requêtes portant un en-tête de widget sautent le limiteur global - le trafic des widgets est déjà throttled en amont par le limiteur par clé du service widget - et il n'y a pas de limiteur dédié au chat, parce que l'agent impose en interne la concurrence par utilisateur, les budgets de tokens et les timeouts en temps réel.

DLP : rédaction avant l'exfiltration

La prévention de perte de données dans Simmetric Chat est un plugin filtre qui scanne à la fois le prompt entrant et la réponse sortante - y compris les flushs progressifs token par token du streaming - et rédige les correspondances avant que le contenu ne quitte votre réseau. Le scanner reconnaît 10 classes de patterns PII intégrés :

  • Adresses email
  • Numéros de carte de crédit
  • Clés API et clés privées
  • Plus les identifiants européens structurés : Partita IVA italienne, codice fiscale et IBAN, ajoutés en v0.22 et semés de manière idempotente

La configuration des patterns est adossée à la base de données et gérée par les admins : activer ou désactiver n'importe quel pattern par ligne, ajouter jusqu'à 50 patterns personnalisés avec validation en direct de la compilation et aperçu de test, et inspecter un panneau d'historique des correspondances DLP filtrable par source (chat ou widget). Les expressions régulières intégrées sont gelées - vous pouvez désactiver un pattern intégré mais pas le réécrire - tandis que les patterns personnalisés portent vos définitions. Les scans qui peuvent lire les patterns configurés les utilisent via un cache à court TTL et retombent sur l'ensemble intégré si la base de données est injoignable, pour qu'une panne de base ne désactive jamais la rédaction.

Deux détails de gouvernance complètent le tableau. Un paramètre DLP_BYPASS_ROLES permet aux admins d'exempter des rôles spécifiques du scan, et chaque bypass génère un événement d'audit consignant qui a bypassé et sur quelle surface - jamais le contenu scanné. Les administrateurs peuvent aussi révéler ou masquer à nouveau les textes correspondants à travers une conversation avec un unique interrupteur, avec une visibilité limitée à la session et masquée par défaut, pour que la rédaction reste réversible pour une revue autorisée mais pas en silence.

Le renforcement le plus subtil de v0.22

Les petits changements comptent parce qu'ils ferment les canaux que les attaquants sondent réellement :

  • Comparaisons timing-safe partout. Chaque comparaison de secrets en clair restante - les barrières du secret du collector, le callback d'import d'archives, le contrôle de clé cache-bust du widget - utilise désormais crypto.timingSafeEqual avec une garde de longueur et échoue en mode fermé quand le secret attendu n'est pas défini.
  • Login résistant à l'énumération. Quand un nom d'utilisateur n'existe pas, le login exécute quand même une comparaison factice de hash avant de répondre, pour que le temps de réponse ne distingue plus les utilisateurs existants des inexistants. Les corps invalides renvoient un 400 structuré plutôt qu'un 401 qui laisserait fuiter les internes de Zod.
  • Mauvaise configuration qui échoue bruyamment. Une mauvaise configuration HMAC côté serveur sur la vérification des clés API renvoie 500, par choix - un secret mal configuré ne doit jamais se déguiser en échec d'authentification.
  • Validation structurée. Les corps de requête sont validés avec des schémas Zod partagés via safeParse ; chaque erreur est une enveloppe uniforme avec des détails par champ, pour que les clients échouent de manière prévisible.

Toute la surface API - tableaux d'endpoints, encadrement des événements SSE et exigences d'authentification par route - est documentée dans la référence API, et une interface Swagger live est incluse dans le serveur.

Lire le guide complet dans la doc →

Articles associés