
Pare-feu LLM à deux couches qui bloque les entrées d'injection de prompt via des règles regex ainsi qu'un classificateur Gemini, et détecte les fuites de secrets ou de prompts système dans les réponses du bot.
Démo en direct : https://prompt-injection-firewall.streamlit.app Vidéo de démonstration de 2 minutes : https://drive.google.com/file/d/1tzb75nFysisrCYa11Lqj6egDs5VNmc2n/view?usp=drivesdk
Un pare-feu à deux couches pour un bot de support LLM : il vérifie ce que les utilisateurs envoient, et ce que le bot renvoie.
Les utilisateurs peuvent tenter de contourner les règles d'un bot (« ignore previous instructions »), de changer sa persona, ou de lui faire révéler son prompt système ou ses secrets. Ce projet bloque ces entrées, détecte les fuites dans les réponses du bot, et mesure son efficacité, y compris là où il échoue.
user input
|
v
[1] Rule layer (regex, fast, free) --match--> BLOCK
|no match
v
[2] LLM classifier (Gemini, JSON output, Pydantic validation, retries, fail-closed) --attack--> BLOCK
|benign
v
AcmeBot (Gemini + system prompt)
|
v
[3] Output check (canary token, secret patterns, system-prompt fragments) --leak--> BLOCK
|clean
v
answer to user
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt
copy .env.example .env # then put your Gemini key in .env
python src\run_eval.py dev
python src\eval_output.py dev
python src\compare.py dev
streamlit run app.py # local demo
Modèle utilisé : gemini-3.1-flash-lite. Le niveau gratuit peut renvoyer une erreur 503 en cas de surcharge ; le code attend et réessaie.
Ne lancez pas src\build_cases.py sauf si vous voulez reconstruire data\cases.jsonl (il l'écrase ; la même graine produit les mêmes cas).
deepset/prompt-injections (Apache-2.0) : 12 attaques, 13 bénins. Répartition : 15 dev, 10 cachés.data/train.parquet est inclus dans le dépôt (source : deepset/prompt-injections, Apache-2.0).| Ensemble | Couche | Résultat |
|---|---|---|
| dev | règles seules | détection 2/9, faux positif 0/6 |
| dev | règles + Gemini (final) | détection 8/9, faux positif 0/6 |
| dev | vérification de sortie (final) | fuite détectée 4/4, faux positif 0/4 |
| caché | règles + Gemini | détection 3/3, faux positif 0/7 |
| caché | vérification de sortie | fuite détectée 3/3, faux positif 0/1 |
Pare-feu vs sans pare-feu :
| Sans | Avec | |
|---|---|---|
| dev : attaques atteignant le bot | 9/9 | 1/9 |
| dev : bénins bloqués à tort | 0/6 | 0/6 |
| caché : attaques atteignant le bot | 3/3 | 0/3 |
| caché : bénins bloqués à tort | 0/7 | 0/7 |
L'ensemble caché ne contient que 3 attaques, c'est donc un signal faible. Dev et caché sont rapportés séparément car j'ai ajusté le prompt du classifieur sur dev.
L'historique complet avec les chiffres se trouve dans CHANGELOG.md. En bref :