Retyc logo blue
Tous les articlesSécurité

Pentest par IA : notre retour d'expérience

Grâce au Cyber Verification Portal d'Anthropic, nous avons fait un pentest de Retyc par Claude, sur notre environnement de développement.
EM

Emilien Mantel

Retyc sert à échanger des fichiers sensibles, et notre promesse tient en une phrase : vos fichiers sont chiffrés sur votre appareil, et personne d'autre que vos destinataires ne peut les lire, pas même nous. Une promesse comme celle-là, il faut la mettre à l'épreuve régulièrement. Jusqu'ici, nous le faisions avec des revues de code, des tests automatisés et des audits par IA, mais toujours limités à de la lecture de code. Le Cyber Verification Portal d'Anthropic nous a permis d'aller plus loin : un vrai pentest de Retyc, mené par Claude. Voici ce que ça a donné.

Le Cyber Verification Portal d'Anthropic

Demander à une IA de chercher des failles pose une question évidente : qu'est-ce qui empêche quelqu'un de s'en servir contre les systèmes des autres ? Anthropic encadre ce type d'usage avec le Cyber Verification Portal. Il faut y être admis avant de pouvoir utiliser Claude pour des travaux de sécurité offensive sur ses propres systèmes.

Nous y avons eu accès, et nous nous sommes fixé un cadre strict. Le pentest a porté uniquement sur notre environnement de développement, jamais sur la production ni sur les données de nos clients. Il s'est appuyé sur des comptes de test dédiés, répartis sur plusieurs organisations et plusieurs formules, pour vérifier l'étanchéité entre clients. Et chaque constat devait donner lieu à un rapport écrit : comment le reproduire, quel impact réel, quelle correction.

L'environnement de développement ne porte aucune des protections qui entourent la production : ni CrowdSec, ni les configurations durcies de notre infrastructure. C'est délibéré. Nous voulions voir les défauts de l'application elle-même, sans qu'une protection périmétrique ne vienne les masquer. Les constats qui suivent sont donc plus sévères que ce qu'un attaquant rencontrerait face à notre production.

Un démarrage laborieux

Tout n'a pas fonctionné du premier coup. La documentation d'Anthropic comportait des erreurs de traduction. Nos premiers tests avec Opus 5.5 ont en réalité tourné sur Opus 4.8. Nous ne l'avons compris qu'avec les avertissements de l'IA elle-même.

La solution a été de passer sur Opus 5 (5, pas 5.5, attention à la nuance !), qui n'a déclenché aucun avertissement. Tout ce qui suit repose sur l'audit mené avec ce modèle.

À la date où nous écrivons, le Cyber Verification Portal ne permet pas encore d'utiliser les modèles Fable ou Opus 5.5.

Comment le pentest s'est déroulé

Le pentest s'est fait en plusieurs passes, dont une reprise complète qui ne réutilisait aucune conclusion de la précédente, et une vérification après chaque vague de correctifs. À noter que Claude avait accès au code source afin d'avoir une vue complète de l'application.

Une règle avant tout : Claude ne devait pas se contenter de lire le code et d'en déduire des failles.

Côté backend, Claude a recensé l'ensemble des endpoints exposés par notre API et relu tout le code (plusieurs dizaines de milliers de lignes). Il a ensuite vérifié ses hypothèses en conditions réelles, avec 4 comptes répartis sur 3 organisations, des appels anonymes et des clés d'API. Chaque constat retenu a été reproduit : aucun n'a été simplement déduit de la lecture du code.

Côté application web, Claude a piloté un Chrome headless. Il s'est connecté, a déverrouillé la clé de chiffrement et a réellement envoyé un fichier contenant un marqueur connu. Il a capturé chaque requête partie vers le serveur, pour voir ce qui quitte vraiment le navigateur.

Entre autres :

  • fuzzing
  • injection de headers HTTP et requêtes mal formatées
  • recherche de XSS et d'injections SQL
  • recherche de problèmes de concurrence et de race conditions
  • vérification de l'étanchéité entre organisations et entre rôles
  • vérification de la sécurité de l'API pour les intégrations (scope des clés, restriction par adresse IP)
  • tentative d'escalade de privilèges dans une organisation

Ce qui a tenu

Le plus important d'abord : le chiffrement de bout en bout a tenu. Pendant l'upload, aucune requête ne contenait le contenu du fichier, son nom ou une clé privée. Les noms et les types de fichiers sont systématiquement chiffrés. Déverrouiller votre clé ne déclenche qu'une seule requête, et votre phrase secrète ne quitte jamais votre navigateur.

L'audit a aussi confirmé que l'étanchéité entre organisations tient sur les données : un utilisateur ne peut ni lire ni modifier les transferts, les datarooms ou les réglages d'une autre organisation. À l'intérieur d'une organisation, un membre ne peut pas s'attribuer plus de droits qu'il n'en a. Pour l'API destinée aux intégrations, les permissions des clés et la restriction par adresse IP sont bien appliquées. Enfin, la connexion suit les bonnes pratiques du protocole OpenID Connect.

Aucune faille XSS n'a été trouvée, et aucune injection SQL n'était possible.

Ce qui a été trouvé

La plupart des constats relèvent de ce qu'on appelle le durcissement : des protections en plus, qui ne corrigent pas une faille exploitable, mais qui limitent les dégâts d'un éventuel problème futur ou d'une erreur de configuration.

Parmi ce que nous avons corrigé ou amélioré :

  • la politique de sécurité du navigateur (CSP), déjà très stricte sur les scripts : seule une exception, nécessaire au composant qui affiche les images, était plus large que besoin. Elle n'autorise plus que le code précis dont ce composant a besoin
  • un serveur qui refuse de démarrer si un secret de configuration a été oublié, au lieu de tourner avec une valeur par défaut
  • des messages d'erreur plus propres quand un jeton de connexion est incomplet
  • verrouillage explicite d'un fichier après upload dans une dataroom

Par contre, 2 constats sortent du lot, et autant en parler franchement.

Dans une dataroom, un utilisateur avec le rôle « contributeur » n'a pas le droit de supprimer de fichiers, et l'API le lui refusait bien. Il pouvait malgré tout arriver au même résultat par un détour : déplacer un dossier vers une dataroom dont il est lui-même propriétaire, puis l'y supprimer. La suppression emportait les fichiers que d'autres membres avaient déposés dans ce dossier, y compris ceux du propriétaire de la dataroom d'origine, et de façon définitive. Il manquait une vérification sur l'appartenance du dossier de destination.

À l'inscription par e-mail, utilisée notamment pour déposer depuis une deposit box, le code de vérification pouvait être deviné en essayant un grand nombre de combinaisons : le code était trop court et rien ne plafonnait le nombre d'essais. La preuve de travail (« proof of work ») exigée à chaque tentative ne suffisait pas, car un même jeton pouvait être rejoué. Le rate limit de notre reverse proxy réduit drastiquement la fenêtre en production, mais nous ne voulons pas faire reposer ce contrôle sur lui : le nombre d'essais est plafonné, et un jeton de preuve de travail ne sert qu'une fois.

Aucun de ces points ne permettait de lire un fichier : le contenu est resté chiffré de bout en bout dans tous les cas. Nous les avons corrigés en priorité.

Les faux positifs

Les valeurs par défaut

Claude a aussi remonté des points qui n'étaient pas de vrais problèmes de sécurité. Il a par exemple signalé que certaines variables de configuration de notre API (sel, secrets...) avaient une valeur par défaut. Ces valeurs ne servaient qu'en développement : en production, elles sont toujours redéfinies.

Nous en avons quand même profité pour poser des règles dans notre configuration : une valeur secrète n'a jamais de valeur par défaut, et le serveur refuse de démarrer si elle manque, même en développement ou dans la CI. Elle doit aussi avoir une taille minimale.

Ces règles sont appliquées en production depuis la bêta de Retyc. Les inscrire explicitement dans notre configuration de développement permet de repérer un oubli avant qu'il n'arrive en production, ou dans les instances « on-premises » de nos clients.

Le mode debug

Claude a aussi relevé que certaines routes de l'API, réservées à nos développeurs, étaient accessibles en « mode debug ». Ce mode ne peut pas être activé en production.

La configuration de Keycloak en développement

En local, notre infrastructure de développement tourne avec Docker Compose. À l'initialisation, les realms Keycloak sont importés depuis un fichier JSON par realm. Claude a noté que cette configuration n'était pas optimale : la détection des attaques par force brute n'était pas activée, et les exigences sur la complexité des mots de passe étaient faibles.

En production, ces points sont configurés correctement. Toute la configuration de Keycloak en production est versionnée, reproductible (par OpenTofu) et auditable.

Ce que nous avons fait des constats

Nous avons traité chaque constat comme un bug à part entière. Une correction par problème, pour pouvoir relire et vérifier chacune séparément. Un test de non-régression pour chaque correction, dont nous avons vérifié qu'il échoue avant le correctif et passe après. Et une contrainte ferme : aucune correction ne devait créer de « breaking change ».

Nous avons corrigé tous les problèmes et toutes les recommandations de durcissement. D'autres améliorations plus lourdes sont planifiées pour les prochaines semaines.

Néanmoins, pour un cas particulier, nous avons dû faire une exception. Une amélioration de la dataroom a nécessité de modifier le comportement d'une route de l'API. Nous avons décidé de l'appliquer immédiatement. De ce fait, toutes les versions de la CLI Retyc antérieures à la version 1.3.0 ne peuvent plus faire d'ajout de fichiers dans une dataroom.

Ce que nous en retenons

Une IA ne remplace pas un audit humain. Mais relire des milliers de lignes de code, recenser des dizaines d'endpoints et rejouer chaque hypothèse avec plusieurs comptes, représente des jours de travail pour une équipe.

Chaque constat arrivait avec sa méthode de reproduction, une évaluation honnête de l'impact, y compris quand il était faible, et une proposition de correction. Claude listait aussi ce qu'il avait vérifié et trouvé sain. C'est cette partie-là que nous n'attendions pas, et c'est celle qui nous a le plus servi.

La relecture humaine reste indispensable. Certaines corrections proposées auraient cassé des usages existants, et il a fallu les discuter et les adapter avant de les appliquer.

Autre enseignement, sur la validation des données : nous attendions trop de Pydantic. EmailStr accepte les majuscules, et il a raison, la partie locale d'une adresse y est sensible selon la norme. Une chaîne contenant un octet nul est elle aussi parfaitement valide en Python, même si PostgreSQL la refuse. Normaliser les entrées reste à notre charge, à la frontière de l'API. Nous l'avons rendu explicite là où ça manquait.

Par ailleurs, afin d'améliorer et cadrer les pentests, nous allons travailler sur des skills dédiés.

Nous comptons refaire l'exercice régulièrement, en plus de nos revues de code et de nos tests.

En résumé

Cet audit a confirmé l'essentiel : vos fichiers restent chiffrés de bout en bout, illisibles par notre équipe comme par n'importe qui d'autre, même si une faille traînait dans notre code.

Sur la quasi-totalité des services de transfert et de stockage, c'est le service qui détient les clés. Le support y a accès, les administrateurs aussi, parfois des tiers.

Chez Retyc, le serveur n'a jamais les clés : même les constats les plus sérieux ne donnaient accès à aucun fichier.

Vous avez des questions sur la sécurité de Retyc, ou vous voulez en savoir plus sur notre démarche ? Écrivez-nous.