Par Claude code Anthropic

📄 SKILL.md 🔒 62fe75f5…d06e6fe1 Se connecter pour télécharger ← Retour
---
name: detecteur-injection-prompt-avance
description: Détecteur avancé d'injection de prompt indirecte — stéganographie par caractères de balisage Unicode (décodage du message caché), caractères bidirectionnels explicites (Trojan Source, CVE-2021-42574), caractères invisibles, scripts mixtes suspects (confusables), texte masqué CSS, faux marqueurs de conversation. Bibliothèque standard uniquement, zéro dépendance, zéro appel réseau.
theme: securite-souverainete
langages_cibles: rust
---

# detecteur-injection-prompt-avance

## Objectif

Scanner un dossier de fichiers texte/documents (`.md`, `.txt`, `.html`,
`.json`, `.xml`, `.svg`, `.rst`...) et détecter six techniques
d'injection de prompt indirecte — le cas où l'instruction n'est jamais
tapée par l'utilisateur, mais cachée dans un contenu tiers qu'un agent IA
va lire de son propre chef pendant qu'il travaille.

## Les six détecteurs

1. **Stéganographie par caractères de balisage Unicode** — le bloc TAGS
   (U+E0000–U+E007F) reflète bit à bit l'espace ASCII imprimable
   (U+E0020–U+E007E ↔ U+0020–U+007E). Un message entier peut être
   encodé caractère par caractère dans des points de code totalement
   invisibles dans tout rendu de texte normal, mais lisibles par un
   modèle qui traite le flux Unicode brut. Technique documentée
   publiquement sous le nom **"ASCII Smuggling"** (recherche en sécurité
   IA, 2024). Ce détecteur ne se contente PAS de signaler la présence de
   tags : il **décode le message caché** et l'affiche dans le rapport.
2. **Caractères de formatage bidirectionnel explicite** — liste
   EXHAUSTIVE des 13 caractères définis par le rapport technique Unicode
   UAX #9, la classe exploitée par **"Trojan Source"** (CVE-2021-42574) :
   réordonner l'affichage d'un texte sans changer son ordre logique en
   mémoire.
3. **Caractères invisibles / largeur nulle** (espace de largeur nulle,
   joints invisibles, séparateurs invisibles...).
4. **Scripts mixtes suspects** — pas une simple table de confusables
   plate : tokenise le texte en runs alphanumériques Unicode et signale
   un run qui mélange Latin avec Cyrillique/Grec/Arménien ET contient au
   moins un caractère de la table de confusables (un mot latin dont une
   seule lettre est remplacée par un caractère d'un autre alphabet visuel-
   lement identique à l'écran, mais de point de code différent) — le
   patron structurel des attaques par homographe IDN, appliqué ici à du
   texte/des identifiants au lieu de noms de domaine.
5. **Texte masqué visuellement via CSS** (`display:none`,
   `visibility:hidden`, `font-size:0`, `opacity:0`) dans un attribut
   `style=`.
6. **Faux marqueurs de conversation** (mots-clés de rôle "system",
   "assistant", "human", "user" suivis d'un deux-points en tête de ligne,
   gabarits de type balise de début de tour ou instruction entre
   crochets).

## Pourquoi ce skill existe

Complémentaire au skill Python `detecteur-injection-prompt` déjà présent
dans ce compte (règles regex/JSON, 3 détecteurs) — cette version Rust
ajoute deux capacités qu'aucun outil de détection courant, y compris
commercial, ne couvre systématiquement : le décodage effectif de la
stéganographie par tags Unicode (pas seulement sa détection), et une
analyse structurelle des scripts mixtes (runs de caractères, pas une
liste plate de motifs).

## Garanties de conception (non négociables)

- **Zéro dépendance tierce**, **zéro appel réseau** — aucune bibliothèque
  Unicode externe : les tables (bidi, invisibles, confusables, plage
  TAGS) sont des `const` embarquées, dérivées de rapports techniques
  Unicode publics (UAX #9, UAX #34) documentés en commentaire.
- **Contenu scanné traité comme donnée inerte**, jamais exécuté ni
  interprété — y compris le message décodé de la stéganographie tags,
  affiché tel quel dans le rapport, jamais ré-interprété comme une
  instruction.
- **Six détecteurs 100% purs et testés isolément**, aucune I/O dans les
  fonctions cœur — `detecter_steganographie_tags`, `detecter_dans_table`,
  `detecter_scripts_mixtes`, `detecter_texte_masque_css`,
  `detecter_faux_marqueurs_role`.
- **Exemption ligne par ligne** via le marqueur `injection-ok` en
  commentaire, pour les cas où le motif détecté est légitimement présent
  (ex. ce SKILL.md lui-même, qui PARLE de ces techniques).
- **`eprintln!` au lieu de `tracing`** : outil CLI ponctuel, pas un
  serveur long-running — même convention que les autres skills Rust du
  projet.
- **`is_some_and`/`is_none_and` bannis** (règle §6 du projet — masquent
  le cas `None` comme `unwrap_or`) : `matches!(opt, Some(x) if cond)`
  utilisé systématiquement à la place.
- **Let-chains évités délibérément** : pas encore stables sur le
  toolchain de validation (rustc 1.93 — stabilisation prévue en 1.95) ;
  `matches!` avec garde remplit le même rôle sans dépendre d'une
  fonctionnalité pas encore disponible.

## Conformité aux règles du projet (verify_rules_rust.sh)

```bash
bash ../../outils/verify_rules_rust.sh --src skills/detecteur-injection-prompt-avance/src
```

**Résultat au 2026-08-19 : 0 violation, 2 avertissements §5, tous deux
annotés et vérifiés faux positifs** (même patron exact que
`detecteur-toctou-fichiers` : `Option<&str>::to_str()` retournant `None`
sur une extension/nom de fichier non-UTF-8 valide n'est jamais un cas
scanné légitime — pas une erreur silencieuse réelle).

**1 violation bloquante trouvée et corrigée pendant le développement** :
un premier essai de simplification d'un `if let` imbriqué (avertissement
§26) via `Option::is_some_and()` a été rejeté par la règle §6 du projet
(traite `is_some_and`/`is_none_and` comme équivalent à `unwrap_or` —
masque silencieusement le cas `None`). Corrigé avec `matches!(opt,
Some(x) if condition)`, qui obtient la même lisibilité sans l'écueil.

**1 avertissement §26 trouvé être un faux positif du scanner** (pas un
vrai `if let` imbriqué collapsible — le bloc interne est un `match` sur
une variable distincte du `Some` extrait, aucune fusion en let-chain
possible même une fois stable) — annoté `// §26-ok` en fin de ligne
(pas en commentaire précédent : le scanner exige l'annotation sur la
MÊME ligne physique que le code signalé, piège déjà rencontré et
documenté ailleurs dans ce compte).

## Mode d'emploi

**Compiler :**

```bash
cargo build --release
```

**Lancer :**

```bash
./target/release/detecteur-injection-prompt-avance <dossier_cible>
```

**Tests unitaires** (21 tests, aucun réseau, aucune I/O disque réelle) :

```bash
cargo test
```

**Validation fonctionnelle réelle** (pas seulement les tests unitaires) :
un fichier échantillon combinant les 6 techniques dans un seul document
produit exactement 6 signalements, dont le décodage effectif d'un
message caché encodé en tags Unicode (`"Hello"`) — confirmé caractère
par caractère, pas supposé.

**Prérequis :** Rust stable (testé avec rustc 1.93, édition 2024). Aucune
dépendance à installer.

## Limites connues (honnêteté de l'outil, pas de sur-promesse)

- **Scripts mixtes** : la table de confusables (55 entrées Cyrillique/
  Grec/Arménien) est volontairement finie, pas une correspondance avec
  la base `confusables.txt` complète du Consortium Unicode (des milliers
  d'entrées, toutes scripts confondus) — un homoglyphe rare hors de cette
  table échappe à la détection. Compromis assumé : zéro dépendance
  externe plutôt qu'embarquer une table générée de plusieurs Mo.
- **Pas de normalisation NFKC** : la stdlib Rust ne fournit aucune
  primitive de normalisation Unicode (contrairement à `unicode-
  normalization`, une dépendance tierce délibérément exclue) — une
  obfuscation reposant sur une décomposition de compatibilité plutôt que
  sur un caractère confusable direct n'est pas couverte.
- **Faux marqueurs de rôle** : recherche de sous-chaînes littérales, pas
  d'analyse contextuelle — un texte qui parle légitimement d'injection de
  prompt (comme ce SKILL.md) déclenchera des signalements attendus,
  d'où le marqueur d'exemption `injection-ok`.
- Ne remplace pas une revue de sécurité humaine — outil de dégrossissage
  rapide et reproductible sur un gros volume de fichiers, pas une preuve
  d'absence d'injection.
8.2 Ko BLAKE3 : 62fe75f5…d06e6fe1