AI Act — contrôle humain et déterminisme
Le règlement européen sur l'IA exige, pour les systèmes à risque, un contrôle humain effectif et une traçabilité des décisions (art. 14). Agentic PhishQual y répond par conception : le verdict est produit par un moteur déterministe et rejouable, jamais par un LLM. Un humain peut comprendre, vérifier et corriger chaque décision.
L'apprentissage passe exclusivement par des leçons validées par un administrateur : aucune adaptation automatique opaque. Chaque décision, raisonnement et leçon appliquée est journalisé.
- Verdict déterministe, non délégué au LLM
- Décisions tracées et explicables
- Adaptation sous validation humaine explicite
- Graphe de raisonnement consultable
RGPD — minimisation et souveraineté
Agentic PhishQual fonctionne intégralement hors-ligne : aucune donnée d'e-mail n'a besoin de sortir de votre environnement. Avant tout traitement par un composant d'explication, les adresses e-mail sont pseudonymisées.
La donnée traitée est minimisée et le système ne dépend d'aucun service cloud tiers obligatoire. Vous restez maître de vos données et de votre infrastructure.
Configuration de l'instance de démonstration publique : pour illustrer l'explication en langage naturel, cette démonstration transmet à un modèle d'explication tiers les familles de données suivantes :
- l'expéditeur pseudonymisé, l'objet pseudonymisé et un extrait du corps pseudonymisé, tronqué à 800 caractères ;
- le score et la décision déjà calculés, les résultats d'authentification SPF, DKIM et DMARC, et la pire réputation observée sur les indicateurs ;
- les indicateurs techniques extraits de l'e-mail — domaines, URL avec leur chemin, adresses IP et empreintes SHA-256 des pièces jointes, avec pour chaque famille le nombre total détecté et, dans la limite des trois premières valeurs de chaque famille : ce sont eux qui fondent l'explication. Comme les autres champs, ils passent par la même pseudonymisation : une adresse e-mail ou un IBAN qui apparaîtrait dans une URL en serait extrait et remplacé par un jeton, mais un domaine, une adresse IP ou une empreinte ne sont pas eux-mêmes des données reconnues par ce mécanisme et restent lisibles.
La pseudonymisation couvre les adresses e-mail, les IBAN dont le code pays (les deux premières lettres) est en majuscules — le reste du numéro peut être écrit en minuscules, et le séparateur entre les caractères, un espace, est optionnel (un IBAN collé sans aucun séparateur est donc reconnu lui aussi) ; seul un IBAN dont le code pays est en minuscules, ou séparé par des tirets, n'est pas reconnu — les numéros de téléphone français et les numéros de sécurité sociale. Elle ne couvre pas les noms de personnes, les adresses postales ni les identifiants internes, pour lesquels aucun motif fiable n'existe sans dictionnaire, ou sans risque de faux positif sur d'autres données. Si une tentative d'injection de prompt est détectée, l'objet et le corps sont intégralement expurgés avant l'envoi.
Le verdict (score et décision) ne dépend jamais de cet appel — il est calculé avant, par le moteur déterministe, et resterait strictement identique sans lui. Un profil de déploiement réellement hors-ligne existe pour qui veut vérifier cette indépendance par lui-même (aucune connexion sortante, verdict inchangé) ; voir deploy/README_deploy.md. La liste des familles de données ci-dessus décrit les deux appels émis au fournisseur tiers pendant l'analyse d'un e-mail — l'explication et les tags consultatifs — et est vérifiée par un test automatique qui capture les deux messages réellement envoyés (tests/test_payload_sortant.py) : si une famille cesse de partir, ou qu'un champ ou un message s'ajoute sans que cette page suive, l'intégration continue échoue. Les garanties de pseudonymisation elles-mêmes — ce qu'elle couvre, ce qu'elle ne couvre pas — relèvent du contrat documenté et testé de app/phishqual/guardrails.py (voir tests/test_guardrails.py), pas de ce test de payload.
Un troisième appel au même fournisseur existe ailleurs dans le produit, hors du périmètre décrit ci-dessus : la traduction d'un feedback analyste en leçon structurée (POST /api/feedback), déclenchée uniquement quand un analyste authentifié soumet un retour sur un verdict déjà rendu — ce n'est pas le chemin d'analyse d'un e-mail. Cet appel n'a lieu que si un modèle est configuré (OLLAMA_BASE_URL) et que la variable d'environnement PHISHQUAL_SORTIE_DONNEES_INTERDITE n'est pas activée — son défaut autorise cette sortie. Cette condition d'activation et ce déclencheur décrivent le code au jour de la rédaction ; contrairement aux familles de données ci-dessous, ils ne sont pas verrouillés par le test cité plus bas. Ce chemin transmet l'objet, pseudonymisé puis tronqué à 60 caractères, et la justification rédigée par l'analyste, elle aussi pseudonymisée mais transmise intégralement, sans troncature, quelle que soit sa longueur — avec les mêmes limites que ci-dessus : les noms de personnes, raisons sociales, montants et références y restent en clair s'ils y figurent, ce n'est pas une anonymisation. Le domaine de l'expéditeur n'est plus transmis du tout par ce chemin, ni en clair ni pseudonymisé. Ce message est lui aussi capturé et vérifié par un test automatique dédié (tests/test_payload_sortant.py) : si l'une des deux familles ci-dessus cesse de partir, ou que le domaine expéditeur y soit de nouveau nommé comme partant, l'intégration continue échoue.
Enrichissement de réputation (VirusTotal) : quand une clé VirusTotal est configurée et que la sortie de données est autorisée, aucune URL n'est jamais envoyée à ce tiers — ni son chemin, ni ses paramètres, quel que soit son hôte. Ce n'est pas une pseudonymisation supplémentaire : c'est la suppression du canal lui-même, qui n'existe plus — la question de sa routabilité ne se pose donc plus. Le signal de réputation sur l'hôte d'une URL reste néanmoins interrogé, via les mêmes canaux domaines et adresses IP que pour tout autre indicateur, sous la même décision de filtrage. Cette décision exclut, avant tout appel et pour un littéral d'adresse en notation standard, en IPv4 et IPv6, une adresse privée, de bouclage, lien-local, réservée (blocs tels que 240.0.0.0/4 en IPv4, ou une plage IANA non encore attribuée telle que 200::/7 en IPv6), partagée entre opérateurs (CGNAT), multicast, ou site-locale IPv6 dépréciée (RFC 3879, fec0::/10) : ni fuite de l'adressage interne du client, ni appel sans valeur d'enrichissement — VirusTotal n'a aucune réputation à donner sur ces plages. Pour un préfixe de transition IPv6 — NAT64, 6to4, IPv4-mappée, IPv4-compatible, IPv4-traduite ou Teredo —, cette même décision est appliquée à la place de celle du conteneur IPv6, jamais en plus : c'est l'IPv4 encapsulée, extraite explicitement par le produit, qui est seule classée — le caractère réservé ou global du conteneur lui-même n'est jamais consulté — pour que le résultat ne dépende jamais de la version de la bibliothèque logicielle sous-jacente. Contrairement aux préfixes de transition ci-dessus, un second préfixe NAT64, réservé par un opérateur à un usage strictement local (64:ff9b:1::/48, distinct du préfixe NAT64 bien connu ci-dessus), n'est PAS traité par extraction d'IPv4 : c'est son conteneur lui-même qui relève de la catégorie réservée décrite plus haut, et il reste donc exclu en bloc, quelle que soit l'IPv4 qu'il encapsulerait — il n'est par construction jamais routable au-delà du réseau qui l'a assigné. Les notations IPv4 non canoniques (décimale, octale, hexadécimale, ou abrégée à moins de quatre groupes) échappent à la reconnaissance même de l'adresse — une limite assumée, relevant en pratique de l'obfuscation d'un attaquant plutôt que de l'infrastructure du client ; l'abréviation IPv6 standard (::) n'est pas concernée : c'est une notation canonique comme une autre, déjà reconnue et filtrée (fe80::1, 200::1, ::1). Une IPv4 dissimulée par un mécanisme de transition IPv6 sans préfixe fixe échappe pour une raison distincte, selon deux cas : un préfixe NAT64 propre à un opérateur ou 6rd, que seul cet opérateur peut identifier ; ou ISATAP, qui l'encode dans l'identifiant d'interface sous n'importe quel préfixe, y compris un préfixe public légitime. Dans les deux cas, la détection nécessiterait une information de configuration externe au paquet lui-même — une seconde limite, assumée séparément de la première. Une adresse publique, elle, continue d'être interrogée en clair : ce mécanisme porte sur la routabilité de l'adresse, distinct de la pseudonymisation décrite plus haut. La suppression du canal URL ferme deux fuites : le chemin et les paramètres d'une URL ne peuvent plus transporter une adresse interne vers ce tiers, et un hôte d'URL illisible n'ouvre plus rien — conséquence assumée : un tel hôte n'est alors simplement plus extrait pour cet enrichissement de réputation, donc plus aucune réputation n'est calculée sur ce point précis (l'URL elle-même continue de partir vers le modèle d'explication, pseudonymisée, comme décrit plus haut) — là où l'ancien canal aurait envoyé l'URL entière à VirusTotal sans aucun contrôle. Vérifié par exécution réelle par tests/test_payload_sortant.py : qu'aucune URL n'est jamais transmise à VirusTotal, et que l'hôte d'une URL publique est bien interrogé via les canaux domaines ou IP.
- Hors-ligne par défaut
- Pseudonymisation des adresses avant traitement explicatif
- Minimisation des données
- Aucune dépendance cloud obligatoire
- Filtre de routabilité IP avant tout appel d'enrichissement
Sécurité — garde-fous agentiques
La boucle de feedback et la couche LLM introduisent des risques propres aux systèmes agentiques. Ils sont traités selon les bonnes pratiques OWASP LLM / Agentic :
- Détection d'injection de prompt sur le contenu et le feedback
- Empoisonnement de mémoire empêché (validation humaine, détection de conflit, effet borné)
- Portée des leçons limitée à des champs autorisés
- Aucune action de remédiation exécutée automatiquement (proposées uniquement)
- Échappement strict des contenus non fiables dans l'interface
Responsabilité
Agentic PhishQual est un outil d'aide à la décision pour le tri de niveau 1. Il propose des actions de remédiation, mais ne les exécute jamais sans intervention humaine. La décision finale et sa mise en œuvre restent de la responsabilité de l'équipe de sécurité.
Les performances publiées sont mesurées sur un corpus de test interne et synthétique (20 e-mails, généré par ce dépôt) : il démontre la reproductibilité du moteur, pas son efficacité sur du courrier réel. Aucune évaluation indépendante n'a été conduite à ce jour, et les chiffres ne doivent pas être lus comme une mesure de performance en conditions réelles. Aucune garantie de détection absolue n'est revendiquée.
Des questions de conformité ?
Essayez l'agent, inspectez son raisonnement et son journal d'audit.
▶Voir l'agent en action