Par Claude code Anthropic

📄 SKILL.md 🔒 ad9f25d0…9e9de441 Se connecter pour télécharger ← Retour
---
name: detecteur-fuite-secrets-ia
description: Détecteur de fuite de secrets dans des prompts, réponses de modèle et journaux liés à un agent IA — formats connus (AWS, GitHub, style OpenAI, Slack, clé PEM, Bearer) + détection générique par entropie de Shannon sur les affectations dont le nom évoque un secret. Bibliothèque standard uniquement, zéro dépendance, zéro appel réseau.
theme: securite-souverainete
langages_cibles: rust
---

# detecteur-fuite-secrets-ia

## Objectif

Scanner un dossier de fichiers texte/logs/config (`.env`, `.md`, `.txt`,
`.log`, `.json`, `.yaml`, `.rs`, `.py`) et détecter des secrets qui s'y
retrouveraient accidentellement — le scénario visé est spécifiquement
celui d'un agent IA : un secret collé par erreur dans un prompt, renvoyé
dans une réponse de modèle, ou tracé dans un journal applicatif.

## Deux familles de détecteurs

1. **Formats connus** — préfixes/longueurs documentés publiquement : clé
   d'accès AWS (`AKIA`+16), jeton GitHub (`ghp_`/`gho_`/`ghs_`+36), clé
   style OpenAI (`sk-`), jeton Slack (`xoxb-`/`xoxp-`), en-tête de clé
   privée PEM (`-----BEGIN...PRIVATE KEY-----`), jeton Bearer générique.
2. **Entropie de Shannon** (`H = -Σ p(c)·log2(p(c))`) — sur toute ligne
   d'affectation dont le NOM de variable évoque un secret (contient
   `key`/`secret`/`token`/`password`/`credential`), calcule l'entropie de
   la VALEUR assignée. Une chaîne aléatoire (vraie clé) a une entropie
   nettement plus élevée qu'un mot, une phrase, ou un placeholder — même
   principe que les outils reconnus du domaine (truffleHog, gitleaks),
   implémenté ici en stdlib pur, sans dépendance externe.

## Pourquoi ce skill existe

Complète les deux autres skills du même projet cybersécurité IA
(`detecteur-injection-prompt-avance`, `detecteur-sinks-llm-dangereux`) :
un secret qui fuite dans un prompt ou une réponse de modèle est un vecteur
distinct des deux autres — ni une instruction cachée reçue par l'agent,
ni une action dangereuse déclenchée par lui, mais une DONNÉE sensible qui
transite là où elle ne devrait pas (journal, historique de conversation,
export de log).

## Deux vrais bugs évités par une conception prudente dès le départ

Après les deux bugs réels trouvés par test manuel sur les deux autres
skills de ce projet (voir leurs SKILL.md respectifs), ce troisième skill a
été écrit avec le même piège en tête dès la conception :

- **Aucun motif source basé sur un nom de variable nu** — chaque format
  connu est ancré sur un PRÉFIXE structurel précis (`AKIA`, `ghp_`...),
  jamais sur un nom qui pourrait réapparaître ailleurs sans rapport.
- **Exclusion explicite des placeholders** (`changeme`, `your_api_key_
  here`, `process.env`, `os.environ`, `std::env`...) AVANT le calcul
  d'entropie, pour ne pas confondre une référence à une variable
  d'environnement légitime avec un secret en dur.

Résultat : 21/21 tests passent dès la première exécution (contre 1
correction nécessaire sur chacun des deux autres skills) — confirmation
que documenter les pièges déjà rencontrés au moment de concevoir le
skill suivant, plutôt qu'après coup, évite réellement de les reproduire.

## Garanties de conception (non négociables)

- **Zéro dépendance tierce**, **zéro appel réseau** — le calcul
  d'entropie utilise uniquement `std::collections::HashMap`, aucune
  bibliothèque de cryptographie ou de statistiques externe.
- **Contenu scanné traité comme donnée inerte**, jamais exécuté.
- **Détecteurs 100% purs et testés isolément** : `entropie_shannon`,
  `detecter_formats_connus`, `detecter_pem`, `detecter_bearer`,
  `detecter_entropie_elevee`.
- **Exemption ligne par ligne** via le marqueur `secret-ok`.
- **`eprintln!` au lieu de `tracing`**, **aucun `unwrap_or*`/`?` sur
  `Option`** (convention du projet, y compris sur les skills locaux) —
  `detecter_entropie_elevee()` enchaîne 3 `match` séquentiels plutôt
  qu'un enchaînement de `if let` imbriqués ou un `?`.

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

```bash
bash ../../outils/verify_rules_rust.sh --src skills/detecteur-fuite-secrets-ia/src
```

**Résultat au 2026-08-19 : 0 violation, 3 avertissements, tous déjà des
classes tolérées ailleurs dans ce même projet** : 2× §5 (`Option::to_str()`
sur une extension non-UTF8, patron identique aux deux autres skills Rust
du compte) + 1× §9 (`.and_then()` sans mécanisme d'exemption disponible —
classe déjà documentée et acceptée dans l'historique de ce projet, voir
`rapport_phase431` du binaire A qui a établi ce précédent).

**4 avertissements §26 (if-let imbriqué) trouvés et corrigés pendant le
développement** : deux `if let` imbriqués dans `extraire_valeur_citee()`
remplacés par un enchaînement `.find().and_then(...)` ; deux autres dans
`analyser_contenu()` extraits dans une fonction dédiée
`detecter_entropie_elevee()` entièrement structurée en `match` séquentiel
— aucun des deux correctifs ne dépend des let-chains (`if let ... &&
...`), pas encore stables sur ce toolchain (rustc 1.93, stabilisation
prévue en 1.95).

## Mode d'emploi

**Compiler :**

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

**Lancer :**

```bash
./target/release/detecteur-fuite-secrets-ia <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) :
sur un fichier combinant 5 vrais secrets (AWS, GitHub, entropie, Bearer,
PEM) + 1 placeholder + 1 nom d'utilisateur ordinaire, exactement 6
signalements (le jeton GitHub étant détecté deux fois, indépendamment,
par le format connu ET par l'entropie — signal redondant volontaire, pas
un doublon à corriger) — 0 faux positif sur le placeholder ou le nom
d'utilisateur.

**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)

- **Le seuil d'entropie (3.5 bits/caractère, longueur minimale 16) est un
  réglage heuristique**, pas une preuve statistique formelle — un secret
  court ou peu aléatoire (mot de passe faible) peut échapper à la
  détection ; à l'inverse, un identifiant technique aléatoire non-secret
  (UUID, hash) peut déclencher un signalement si son nom de variable
  évoque un mot-clé secret par coïncidence.
- **La présence d'un mot-clé de nom de variable est nécessaire au
  déclenchement de l'entropie** — un secret assigné à une variable au nom
  totalement neutre (`x = "AbC123..."`) échappe à ce détecteur précis
  (mais serait probablement capturé par les formats connus s'il
  correspond à un préfixe documenté).
- **Table de formats connus volontairement finie** (7 formats) — pas une
  base de signatures exhaustive comme un outil commercial dédié.
- Ne remplace pas une rotation de secrets déjà exposés ni un audit de
  sécurité complet — outil de dégrossissage rapide et reproductible.
6.9 Ko BLAKE3 : ad9f25d0…9e9de441