Articles techniques

Analyses de fond sur la sécurité des LLM.

Au-delà des résumés de référentiels : des explications qui vont jusqu'au mécanisme sous-jacent.

Pourquoi un LLM ne peut pas distinguer une instruction d'une donnée

La prompt injection n'est pas un bug qu'on corrige avec un patch. C'est une conséquence directe de l'architecture des transformers autorégressifs tels qu'on les utilise aujourd'hui. Comprendre pourquoi permet de comprendre pourquoi aucun guardrail seul ne suffit.

Un seul canal pour tout faire transiter

Un LLM reçoit son entrée comme une séquence de tokens unique. Qu'il s'agisse du system prompt défini par le développeur, de la question de l'utilisateur, ou du contenu d'une page web récupérée par un outil de recherche, tout est concaténé dans la même fenêtre de contexte et traité par le même mécanisme d'attention. Les rôles de message (system, user, tool) sont une convention de formatage apprise pendant l'entraînement — pas une barrière de sécurité au sens où l'entend un système d'exploitation avec ses espaces mémoire protégés.

En sécurité applicative classique, on résout ce type de problème par une séparation stricte du canal de contrôle et du canal de données (requêtes SQL paramétrées, par exemple : le code SQL et les valeurs ne partagent jamais le même parsing). Pour un LLM généraliste actuel, il n'existe pas d'équivalent structurel : le modèle « lit » tout, et rien ne l'empêche architecturalement d'interpréter un fragment de donnée comme une instruction à suivre.

Pourquoi le fine-tuning d'alignement ne suffit pas

On pourrait penser qu'entraîner le modèle à toujours obéir au system prompt en priorité résout le problème. Cela aide — c'est d'ailleurs la logique derrière les techniques d'alignement par instruction hiérarchisée — mais ça ne l'élimine pas : le modèle reste un système probabiliste, pas un vérificateur de règles déterministe. Une formulation suffisamment habile (changement de langue, encodage, jeu de rôle fictif, répétition) peut faire glisser la distribution de probabilité vers la sortie voulue par l'attaquant, exactement comme un test statistique peut être trompé par un cas limite bien choisi.

Ce qui en découle concrètement

  • Aucun guardrail n'est définitif — chacun réduit la probabilité de succès d'une attaque, aucun ne la ramène structurellement à zéro. D'où le defense in depth.
  • Le périmètre d'impact compte plus que la prévention parfaite — puisqu'on ne peut pas garantir qu'aucune injection ne passera jamais, la priorité est de limiter ce qu'une injection réussie peut faire (voir least privilege).
  • Tout contenu non écrit par le développeur est une entrée non fiable — y compris les résultats d'outils, les documents RAG, les réponses d'autres agents dans un système multi-agents.
↑ haut de l'article

Concevoir un agent avec accès outils sans lui donner les clés du système

Dès qu'un agent peut appeler des outils, la question n'est plus seulement « le modèle peut-il halluciner ? » mais « que peut faire l'attaquant qui contrôle le modèle pendant trente secondes ? ». C'est le principe qui doit guider toute conception d'agent avec accès outils.

Partir du pire cas, pas du cas nominal

La question de conception n'est pas « quel outil cet agent doit-il utiliser pour bien fonctionner » mais « si une injection de prompt réussissait à l'instant T, quelle est la pire action que l'agent pourrait déclencher avec les outils dont il dispose ? ». Cette inversion de perspective change concrètement les décisions d'architecture.

Trois leviers concrets

  • Granularité des outils — préférer lire_email(id) et marquer_traité(id) à un outil générique executer_action_boite_mail(commande). Plus un outil est spécifique, plus son rayon de dégât est borné.
  • Permissions scopées à la session, pas à l'application — un agent qui agit pour le compte d'un utilisateur donné ne doit jamais hériter des permissions larges du compte de service applicatif ; il doit obtenir un jeton scopé aux ressources de cet utilisateur précis.
  • Confirmation hors bande pour les actions irréversibles — un envoi d'email externe, une suppression, un paiement : la décision de l'agent déclenche une demande de confirmation portée par un canal que l'attaquant ne contrôle pas (pas un simple message texte que l'agent pourrait aussi halluciner comme « confirmé »).

Le piège du multi-agents

Un système multi-agents (un agent planificateur qui délègue à des agents spécialisés) ne réduit pas le risque : il le déplace. Le contenu produit par un agent compromis devient une entrée non fiable pour l'agent suivant. Le principe de séparation instructions/données doit donc s'appliquer aussi entre agents, pas seulement entre l'utilisateur et le premier agent de la chaîne.

↑ haut de l'article

RAG et empoisonnement de corpus : le vecteur d'attaque qu'on oublie

La plupart des discussions sur la sécurité du RAG se concentrent sur la fuite de documents confidentiels via le retrieval. Le sens inverse — injecter du contenu malveillant dans le corpus pour qu'il soit retrouvé et exécuté comme instruction — est tout aussi réel et bien moins souvent testé en audit.

Le mécanisme

Un système RAG d'entreprise indexe fréquemment des sources partiellement ou totalement externes : pages web publiques, tickets de support, emails entrants, documents partagés par des tiers. Si l'attaquant peut déposer du contenu dans une de ces sources — publier une page web, soumettre un ticket, envoyer un email — il peut y cacher une instruction (texte invisible, encodage, formulation neutre en apparence) conçue pour être retrouvée lors d'une requête plausible et injectée telle quelle dans le contexte du modèle au moment de la génération.

Contrairement à l'empoisonnement de données d'entraînement — coûteux, lent, nécessitant un accès au pipeline de pré-entraînement — l'empoisonnement d'un corpus RAG est rapide, peu coûteux, et ne nécessite qu'un accès en écriture à une source déjà indexée. C'est structurellement une prompt injection indirecte, mais avec une persistance et une portée différentes : le contenu piégé reste actif tant qu'il n'est pas retiré de l'index.

Pistes de détection et de mitigation

  • Provenance et scoring de confiance des sources — un document provenant d'une source externe non modérée devrait porter un niveau de confiance inférieur, exploitable pour pondérer ou filtrer le contexte avant génération.
  • Détection d'anomalies textuelles — texte invisible (même couleur que le fond dans un PDF/HTML), caractères Unicode trompeurs, formulations impératives incongrues dans un document informatif, sont des signaux détectables par des scanners dédiés (voir outillage).
  • Séparation stricte contexte récupéré / instruction système — délimiter explicitement dans le prompt final où commence et où finit le contenu récupéré, pour réduire (sans l'éliminer) l'ambiguïté que le modèle pourrait exploiter à son détriment.
  • Ré-évaluation périodique du corpus — un contenu jugé sûr à l'indexation peut être modifié après coup si la source reste modifiable (wiki, page web) ; un audit périodique du corpus indexé est nécessaire, pas seulement un contrôle à l'ingestion.
↑ haut de l'article