Pourquoi ce module
L'injection de prompt occupe la première place du Top 10 OWASP LLM (LLM01) depuis 2023, sans avoir jamais été détrônée. Et Microsoft signale la variante indirecte comme la technique la plus employée dans les incidents réels.
Ce module explique pourquoi, et surtout : où se trouve réellement la surface d'attaque. La réponse surprend, et c'est elle qu'on attend en entretien — ce n'est pas la question de l'utilisateur.
Objectifs pédagogiques
- Distinguer injection directe et indirecte, et dire laquelle compte
- Localiser la surface d'attaque d'un RAG sur corpus tiers
- Concevoir un détecteur déterministe et justifier l'absence de LLM dedans
- Expliquer pourquoi on met en quarantaine plutôt que de supprimer
- Décrire le problème du député confus et sa parade
- Justifier le caviardage de PII par marqueur typé
Plan détaillé
- Injection directe et indirecte
- Où est vraiment la surface d'attaque
- Détecter sans LLM
- Quarantaine plutôt que suppression
- Le député confus
- Les PII
- Quand le garde-fou est lui-même le problème
- Glossaire du module
1. Injection directe et indirecte
Chargement du schéma…
Directe : l'utilisateur tente lui-même de détourner le système. C'est visible, c'est journalisé, et l'utilisateur est identifiable.
Indirecte : l'instruction malveillante est dans le contenu que le modèle lit — une page web, un PDF, un ticket, un message d'erreur. L'utilisateur ne fait rien de mal. L'attaquant a déposé son piège des semaines plus tôt.
C'est la variante qui compte, pour trois raisons : elle est asynchrone, elle passe par un canal de confiance (le corpus est censé être la source de vérité), et un seul document empoisonné compromet toutes les réponses portant sur ce sujet.
2. Où est vraiment la surface d'attaque
« Votre corpus est fait de PDF tiers téléchargés sur le web. Comment défendez-vous le système contre l'injection de prompt ? »
La première phrase de la réponse est la plus importante :
« La surface d'attaque n'est pas la question de l'utilisateur, c'est le corpus. »
Ces PDF entrent dans le contexte à chaque réponse. Un document piégé compromet tout ce qui concerne cet équipement, sans que personne n'ait jamais rien saisi de malveillant.
Chargement du schéma…
Conséquence de conception : le filtrage se fait à l'ingestion, pas à la requête. Filtrer à la requête, c'est payer le coût du contrôle à chaque question et laisser le document piégé dans l'index.
3. Détecter sans LLM
Le réflexe naturel — « on demandera à un modèle si ce texte est malveillant » — est une erreur, et savoir dire pourquoi est un excellent point.
🎯 Les deux arguments.
- Un filtre qui appelle un modèle est vulnérable à l'entrée qu'il filtre. On lui demande d'analyser un texte conçu pour détourner des modèles. Le garde-fou devient une surface d'attaque supplémentaire.
- Son verdict n'est pas reproductible. En audit, il faut pouvoir dire pourquoi ce document a été bloqué. « Un modèle a estimé que » n'est pas une réponse opposable.
Le bon critère de détection est le second point d'élégance de ce module :
Le critère n'est pas « ce texte est-il malveillant ? » — c'est indécidable. C'est : « ce texte s'adresse-t-il à un assistant plutôt qu'à un technicien ? »
Une notice de transmetteur ne dit jamais « ignore les instructions précédentes ». La détection ne cherche pas une intention, elle cherche un registre de discours qui n'a rien à faire là.
Les signaux exploitables, tous déterministes :
| Signal | Ce qu'il révèle |
|---|---|
| Formules d'adressage à un assistant | « ignore previous instructions », « you are now », « from now on » |
| Caractères de largeur nulle en excès | Texte caché à l'œil humain, lu par le modèle |
| Contrôles bidirectionnels en excès | Réordonnancement visuel : ce qui s'affiche ≠ ce qui est lu |
| Texte en couleur de fond, taille minuscule | Même principe, côté PDF |
| Densité anormale d'impératifs à la deuxième personne | Registre de consigne dans un document descriptif |
⚠️ Le piège du
\bsur corpus français. La frontière de mot\bdes expressions régulières est définie sur[A-Za-z0-9_]. Sur un corpus français, les caractères accentués ne sont pas des caractères de mot :\bignore\bpeut donc matcher au milieu deignoréou produire des frontières inattendues autour de mots accentués. C'est une question de QCM classique, et un vrai bug de production.
4. Quarantaine plutôt que suppression
C'est le troisième point du module, et il vient d'une confrontation au réel.
Un détecteur passé sur le corpus réel matche des pages légitimes. Cas vécu : une page d'étalonnage de détecteur de gaz contenant la formule « from now on » dans une phrase parfaitement normale. Supprimée, cette page disparaissait des réponses — et c'est une page de sécurité.
Chargement du schéma…
Pourquoi la quarantaine :
- Un détecteur déterministe a forcément des faux positifs — c'est le prix de la reproductibilité
- Un faux positif supprimé est une perte d'information silencieuse
- La quarantaine rend la décision révisable par un humain
- Elle laisse une trace : on sait ce qui a été écarté et pourquoi
Le corollaire non négociable : un document en quarantaine doit être exclu de tous les canaux. S'il reste accessible par un autre outil, par une autre requête, ou par un autre chemin de recherche, la quarantaine ne sert à rien. C'est le lien direct avec l'invariant du module F3 : le filtre s'applique avant la fusion, pas après.
5. Le député confus
Confused deputy : un composant privilégié est amené à agir, pour le compte d'un tiers non autorisé, en utilisant ses privilèges à lui.
Chargement du schéma…
C'est exactement le scénario du module F3 : un organizationId passé en argument d'outil serait choisi par le modèle, qui lit le corpus, donc influençable par un document piégé.
Les parades, dans l'ordre d'efficacité :
- Ne jamais dériver l'autorité du contenu. L'identité vient du transport, jamais des arguments d'outil.
- Moindre privilège. Un agent qui lit du contenu externe n'a pas d'outil d'écriture non borné.
- Séparer les rôles. L'agent qui lit l'externe et celui qui agit ne sont pas le même, et le second traite la sortie du premier comme non fiable.
- Journaliser l'autorité effective de chaque appel, pour pouvoir reconstituer après coup.
💡 La règle générale, qui vaut réponse d'entretien : « Le retour d'un composant qui a lu du contenu externe est lui-même du contenu externe. Le fait qu'il ait transité par mon code ne le rend pas fiable. »
6. Les PII
PII — Personally Identifiable Information, données à caractère personnel.
Deux questions d'entretien reviennent, et elles ont des réponses contre-intuitives.
Pourquoi remplacer par un marqueur typé plutôt que supprimer ?
Un caviardeur qui remplace m.dubois@exemple-client.fr par [EMAIL] plutôt que de l'effacer préserve trois choses :
| Ce qui est préservé | Pourquoi ça compte |
|---|---|
| La structure de la phrase | « Contactez [EMAIL] pour la maintenance » reste compréhensible ; « Contactez pour la maintenance » ne l'est plus |
| Le type de la donnée retirée | Le modèle sait qu'il manque une adresse, pas un mot quelconque — il peut répondre « contactez le responsable maintenance » |
| La traçabilité | On peut compter et auditer ce qui a été caviardé |
Supprimer purement produit des phrases mutilées que le modèle interprète mal — et parfois complète de lui-même, ce qui est exactement le contraire du but recherché.
Pourquoi exclut-on d'ordinaire les noms de personnes d'un détecteur de PII sur un corpus industriel ?
Parce que le taux de faux positifs est ingérable : les noms propres abondent dans les noms d'équipements, de marques, de normes et de lieux — Pascal, Kelvin, Bourdon, Venturi — des noms de personnes devenus des unités, des normes ou des pièces. Un détecteur de noms sur ce corpus caviarderait le vocabulaire technique lui-même, rendant les documents inutilisables.
On garde donc les détecteurs à forme reconnaissable : adresses e-mail, téléphones, IBAN, numéros de sécurité sociale, immatriculations. Leur forme les rend détectables sans ambiguïté.
⚠️ Ce compromis doit être énoncé au client, pas caché. Dire « nous ne détectons pas les noms de personnes, voici pourquoi, et voici ce que nous faisons à la place » est une réponse professionnelle. Laisser croire à une couverture complète est une faute qui se paiera au premier audit.
7. Quand le garde-fou est lui-même le problème
Trois défauts qui touchent le code du garde-fou, pas le système qu'il protège. Ils sont d'autant plus graves que ce code tourne sur chaque passage de chaque réponse.
7.1 Le détecteur qui devient le déni de service
Une expression régulière à quantificateurs imbriqués — (a+)+, (\w+\s*)+ — expose au ReDoS : sur certaines entrées, le temps d'évaluation explose exponentiellement.
L'ironie est totale : le contrôle de sécurité devient le déni de service.
Et ça compte davantage ici qu'ailleurs, pour deux raisons cumulées : l'entrée est faite de documents tiers non fiables, et le filtre tourne sur chaque passage de chaque réponse. Un attaquant qui connaît votre regex n'a qu'à déposer le document qui la fait exploser.
7.2 Le bug du lastIndex
Symptôme déroutant : la même regex rate des correspondances sur certains passages et pas d'autres, sans logique apparente.
Une regex de niveau module déclarée avec le drapeau
/gporte un état mutable :lastIndexpersiste entre les appels. Le bug dépend donc de l'ordre des passages traités — et il est invisible à un test qui vérifie un seul passage.
Le correctif : réinitialiser lastIndex, ou construire la regex à chaque appel. Le second est plus sûr.
7.3 Ce qui limite les dégâts quand le filtre est franchi
Une injection finira par passer. La question n'est pas si, mais ensuite.
La défense en profondeur suppose que la première couche échoue. Une instruction obéie est sans effet si elle n'atteint aucun canal sortant — d'où le contrôle d'egress en seconde ligne, et non le durcissement du prompt.
Concrètement : borner ce que l'agent peut émettre — pas d'appel réseau arbitraire, pas d'écriture non bornée, pas d'exfiltration par URL d'image. Durcir le prompt en deuxième couche revient à mettre deux fois la même serrure.
7.4 Red-teamer ses propres garde-fous
Exercice qu'on vous demandera de dérouler. Le premier point est le plus discriminant :
On attaque le corpus, pas le champ de saisie. Un red-teaming qui se contente de taper « ignore tes instructions » dans l'interface teste la mauvaise surface.
Le protocole, en six temps :
- Injecter des documents piégés dans le corpus de test — c'est le vrai vecteur
- Instructions cachées par caractères de largeur nulle, texte blanc sur blanc, corps de police minuscule
- Balayage par paraphrase : reformuler la même instruction de vingt façons pour trouver où les motifs lâchent
- Attaquer le filtre lui-même — entrées conçues pour déclencher un ReDoS (§ 7.1)
- Tester délibérément les faux positifs, sur de vraies pages du corpus client
- Rapporter les deux taux : détection et faux positifs. Un rapport qui ne donne que le premier est un rapport publicitaire
🎯 La relance : « votre balayage casse le détecteur à la neuvième paraphrase — un détecteur à motifs vaut-il seulement la peine ? »
Oui, et il faut savoir pourquoi : il n'a jamais été la garantie, il est la première couche. Il élimine à coût nul le volume d'attaques non ciblées, il est reproductible en audit, et il ne peut pas être retourné contre lui-même comme le serait un classifieur. Ce qui arrête la neuvième paraphrase, c'est le contrôle d'egress (§ 7.3) — la couche qui suppose que la première a échoué.
8. Glossaire du module
| Terme (EN) | Terme (FR) | Définition |
|---|---|---|
| Prompt injection | Injection de prompt | Détourner un modèle par du texte fourni en entrée |
| Direct injection | Injection directe | Vient de l'utilisateur lui-même |
| Indirect injection | Injection indirecte | Vient d'un contenu lu par le modèle |
| LLM01 | — | Rang de l'injection au Top 10 OWASP LLM ; 1ᵉʳ depuis 2023 |
| Corpus poisoning | Empoisonnement de corpus | Déposer un document piégé dans la base documentaire |
| Confused deputy | Député confus | Composant privilégié instrumentalisé par un tiers |
| Least privilege | Moindre privilège | Ne donner que les droits strictement nécessaires |
| Quarantine | Quarantaine | Exclusion réversible et tracée, plutôt que suppression |
| False positive | Faux positif | Contenu légitime signalé à tort |
| Zero-width character | Caractère de largeur nulle | Caractère invisible à l'œil, lu par le modèle |
| Bidi control | Contrôle bidirectionnel | Caractère réordonnant l'affichage du texte |
| PII | Données à caractère personnel | Information identifiant une personne |
| Redaction | Caviardage | Remplacement d'une donnée sensible par un marqueur |
| Defense in depth | Défense en profondeur | Plusieurs couches indépendantes plutôt qu'un rempart |
| ReDoS | Déni de service par regex | Quantificateurs imbriqués → temps d'évaluation explosif |
lastIndex | — | État mutable d'une regex /g ; provoque des ratés dépendant de l'ordre |
| Egress control | Contrôle d'egress | Borner ce que l'agent peut émettre — 2ᵉ ligne après le filtre d'entrée |
Atelier (75 min)
- La première phrase (15 min) — répondez à « how would you defend a RAG against prompt injection when the corpus is third-party PDFs? » en commençant impérativement par la localisation de la surface d'attaque. En anglais, 90 secondes.
- Sans LLM dans le garde-fou (20 min) — donnez les deux arguments, puis répondez à la relance : « et si on utilisait un petit modèle rapide juste pour ça ? »
- Le faux positif (20 min) — racontez le cas de la page d'étalonnage et concluez sur quarantaine vs suppression.
- Les deux questions PII (20 min) — marqueur typé, et exclusion des noms. À voix haute.
Pour aller plus loin
- 🎯 Parcours : F4 — Évaluation ← → F6 — Observabilité & coût
- 📚 Approfondissement : J4 — Sécurité IA et garde-fous et M9 — Constitutional AI
- 🛠 Entraînement : thème
safety_guardrailsde la banquefransys-fde— 12 QCM