Le blog sécurité de HisnLabs

Par HisnLabs Security & Research Team · Publié · 8 min de lecture

Tester un garde-fou IA avec des jeux de tests publics, pas à pas

Tester un garde-fou IA avec des jeux de tests publics, pas à pas

Tous les fournisseurs de garde-fous vous diront que leur produit fonctionne. Bonne nouvelle : vous n’êtes pas obligé de les croire sur parole. Des chercheurs ont publié des collections ouvertes de messages de test que chacun peut lancer, et un après-midi attentif avec elles vous en apprend davantage que n’importe quelle brochure. Ce tutoriel présente la méthode que nous utilisons chez HisnLabs, pour que vous puissiez l’appliquer à n’importe quel garde-fou : celui que vous construisez, celui que vous achetez, ou deux que vous comparez.

Il s’adresse aux ingénieurs, mais les règles du milieu concernent tout le monde. Un responsable qui les connaît peut lire les résultats de n’importe quel fournisseur et voir tout de suite s’ils veulent dire quelque chose.

L’idée derrière chaque étape

Pour le test, un garde-fou est une fonction : du texte entre, un score entre 0 et 1 sort, qui signifie « quelle est la probabilité que ce soit une attaque ? ». Un seuil transforme le score en décision. Chaque jeu de tests public est une liste de textes dont la bonne réponse est connue. On applique la fonction à chaque texte, et on compte trois choses.

  • Repérées : les attaques dont le score atteint ou dépasse le seuil, sur l’ensemble des attaques.
  • Bloqués à tort : les textes sûrs dont le score atteint ou dépasse le seuil, sur l’ensemble des textes sûrs.
  • Temps ajouté : la durée d’un appel, pour un message typique et pour les cas les plus lents, sur un matériel précisé.

C’est toute la mesure. Le reste de ce tutoriel explique comment la faire honnêtement.

Quatre règles qui donnent un sens aux chiffres

1. Ne jamais tester sur ce qui a servi à l’entraînement

Beaucoup de jeux de tests publics sont construits à partir des mêmes collections de jailbreaks que celles dont les modèles de garde apprennent. Si un jeu recoupe les données d’entraînement, le garde-fou a déjà vu les réponses, et son score ne dit rien des attaques nouvelles. Vérifiez chaque jeu de tests par rapport aux sources d’entraînement, et écartez ceux qui se recoupent. Si vous évaluez le modèle d’un fournisseur, lisez sa fiche technique pour savoir sur quoi il a été entraîné, et indiquez-le à côté de son chiffre.

2. Choisir le seuil avant de regarder les tests

Fixez le seuil sur un jeu de validation distinct, selon une règle écrite à l’avance, par exemple « le seuil le plus élevé qui ne bloque pas plus d’une petite part fixée des messages sûrs de validation ». Lancez ensuite les tests une seule fois. Déplacer le seuil jusqu’à ce que le score de test soit flatteur gonfle le résultat, et il ne tiendra pas sur le trafic réel.

3. Toujours publier les deux côtés

Un garde-fou qui bloque tout repère toutes les attaques. C’est pourquoi un chiffre d’attaques repérées, seul, ne veut rien dire. Il doit toujours être accompagné d’un chiffre de blocages injustifiés, mesuré sur un jeu qui contient des textes sûrs. Les auteurs de CyberSecEval 2, chez Meta, font la même remarque et proposent pour cela un taux de refus injustifiés [5]. Notre article sur les garde-fous qui ne gênent pas vos utilisateurs explique pourquoi ce second chiffre décide souvent si un garde-fou reste activé.

4. Dire ce que mesure chaque jeu, et publier séparément

Les jeux de tests mesurent des choses différentes. Certains contiennent des demandes nuisibles, comme des instructions dangereuses, ce qui relève de la sécurité des contenus. D’autres contiennent de la manipulation, des tentatives de contourner les instructions de l’assistant, que l’OWASP appelle injection de prompt [7]. Un garde-fou conçu pour l’un paraîtra faible sur l’autre, par construction. Publiez par jeu et par groupe de langues, jamais un chiffre unique mélangé.

Publier chaque taux avec son n et une marge de confiance

« 96 sur 100 repérées » sur 55 attaques ou sur 5 000 attaques, ce ne sont pas les mêmes affirmations. Avec peu de messages, le hasard seul fait beaucoup varier le résultat. La façon honnête de le montrer est une marge de confiance. Pour ce type de taux, l’intervalle de Wilson est un bon choix par défaut : il s’utilise sans risque sur de petits échantillons et des observations déséquilibrées, et il ne se réduit pas à une largeur nulle quand un taux est proche de 0 ou de 1, contrairement à l’approximation normale plus simple [6]. Quelques lignes de Python suffisent :

wilson.py
from math import sqrt

def wilson(k, n, z=1.96):
    """95 in 100 confidence range for k successes out of n."""
    p = k / n
    d = 1 + z * z / n
    centre = (p + z * z / (2 * n)) / d
    half = z * sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / d
    return round(centre - half, 3), round(centre + half, 3)

print(wilson(53, 55))      # (0.877, 0.99)
print(wilson(4800, 5000))  # (0.954, 0.965)
print(wilson(0, 250))      # (0.0, 0.015)

Ces chiffres concernent un garde-fou hypothétique, pour montrer l’effet. Le même taux observé, environ 96 sur 100, donne une marge d’environ 88 à 99 sur 100 avec 55 attaques, et d’environ 95 à 97 avec 5 000. La dernière ligne compte pour les blocages injustifiés : un garde-fou qui n’a bloqué aucun de 250 messages sûrs peut encore en bloquer jusqu’à environ 1,5 sur 100 en usage réel. Un fournisseur qui affiche « 0 blocage injustifié » sans donner le n ne vous apprend pas grand-chose.

Étape 1 : GuardBench, pour une première vue d’ensemble

GuardBench, de Bassani et Sanchez, a été présenté à la conférence EMNLP 2024. Il rassemble 40 jeux de données d’évaluation de sécurité derrière une seule bibliothèque Python, et son article a aussi publié de nouveaux jeux de modération en allemand, français, italien et espagnol [1]. La bibliothèque est open source sous licence EUPL-1.2 ; chaque jeu garde sa propre licence, et certains demandent une inscription ou une connexion à Hugging Face [2]. Installez-la dans son propre environnement :

Terminal
# un environnement séparé pour les outils de test
python -m venv .venv-guardbench
.venv-guardbench/bin/pip install guardbench

Vous fournissez à la bibliothèque une seule fonction, qui reçoit un lot de conversations et renvoie pour chacune la probabilité qu’elle soit dangereuse. Ici, elle appelle un garde-fou qui expose un petit point d’accès de notation ; remplacez l’adresse par celle de votre garde-fou ou de l’API d’un fournisseur.

run_guardbench.py
from guardbench import benchmark
import requests

GUARD_URL = "http://127.0.0.1:8810/classify"  # your guardrail's scoring endpoint

def moderate(conversations, **kwargs):
    # conversations: a list of chats, each a list of {"role": ..., "content": ...}
    # return one float per chat: the probability that it is unsafe
    return [requests.post(GUARD_URL, json={"text": c[-1]["content"]}).json()["score"]
            for c in conversations]

benchmark(
    moderate=moderate,
    model_name="my-guard 0.1.0",
    batch_size=16,
    datasets=["xstest", "jbb_behaviors"],  # choose the sets that match what the guard is for
    metrics=["f1", "recall"],
)

Deux choix comptent ici. D’abord, choisissez les jeux qui correspondent au rôle du garde-fou, pas tous les jeux : un garde-fou contre l’injection de prompt et un garde-fou de sécurité des contenus ne doivent pas être évalués sur les mêmes jeux. Ensuite, incluez XSTest. Ses 250 demandes sûres qui ont l’air dangereuses, à côté de 200 contre-exemples dangereux, en font l’une des meilleures mesures publiques des blocages injustifiés [3]. GuardBench calcule ses indicateurs avec un seuil fixe de 0,5 ; calculez aussi votre propre seuil choisi à l’avance à partir des scores enregistrés, et précisez lequel chaque chiffre utilise.

Étape 2 : l’injection de prompt de CyberSecEval, pour la manipulation

Le projet Purple Llama de Meta publie CyberSecEval sous licence MIT. Ses tests d’injection de prompt évaluent la vulnérabilité d’un modèle aux attaques dans lesquelles une partie du prompt, issue d’une entrée utilisateur non fiable, contient des instructions destinées à détourner la tâche d’origine du modèle [4]. Il existe un fichier en anglais et un fichier multilingue traduit automatiquement. Chaque ligne est une attaque : ce jeu ne mesure donc que les attaques repérées. Associez-le à un jeu de textes sûrs, comme XSTest ou le vôtre.

Il y a deux façons de l’utiliser. La plus rapide consiste à noter chaque attaque directement avec votre garde-fou, comme à l’étape 1, et à compter combien dépassent votre seuil, langue par langue. La plus complète utilise l’outil de Meta : il envoie chaque prompt système et chaque attaque à un chatbot, puis un second modèle, dans le rôle de juge, décide si le chatbot s’est fait piéger.

Terminal
# récupérer les tests
git clone --depth 1 https://github.com/meta-llama/PurpleLlama
cd PurpleLlama
# lancer les tests d’injection de prompt contre un chatbot, avec un modèle juge
python3 -m CybersecurityBenchmarks.benchmark.run --benchmark=prompt-injection --prompt-path="$DATASETS/prompt_injection/prompt_injection.json" --response-path="$DATASETS/prompt_injection/prompt_injection_responses.json" --judge-response-path="$DATASETS/prompt_injection/prompt_injection_judge_responses.json" --stat-path="$DATASETS/prompt_injection/prompt_injection_stat.json" --judge-llm=<JUDGE> --llm-under-test=<MODEL>

Lancez-le deux fois : une fois avec le chatbot seul, une fois avec le même chatbot derrière le garde-fou, en comptant un message bloqué comme « non piégé ». La différence entre les deux passages, c’est ce qu’apporte le garde-fou, et c’est la question qui intéresse vraiment un acheteur. Nommez le modèle juge dans votre rapport : ses propres erreurs font partie du résultat.

Étape 3 : tester dans les langues de vos utilisateurs

Les jeux publics sont surtout en anglais. Si vos utilisateurs écrivent en arabe, construisez votre propre jeu réservé : des messages sûrs réalistes et des attaques en arabe standard, en dialectes du Golfe et d’Égypte, en arabizi et en arabe mêlé d’anglais, chacun aussi sous une forme entièrement vocalisée et une forme vocalisée au hasard. Ne l’utilisez jamais pour l’entraînement. Publiez chaque groupe séparément : pour une banque à Dubaï, un garde-fou bon en anglais et faible en arabizi n’est pas le produit que sa moyenne laisse croire.

Ce que contient un rapport digne de confiance

  • Pour chaque jeu : son nom, un lien, sa licence, et s’il est public ou issu de votre propre jeu réservé.
  • Par groupe de langues : le taux d’attaques repérées et le taux de blocages injustifiés, chacun avec son n et une marge de confiance à 95 sur 100.
  • Le nom et la version du modèle, la date, et la règle qui a servi à choisir le seuil.
  • Le temps ajouté par message, typique et pour les cas lents, avec le matériel et la longueur des messages.
  • Les éventuelles campagnes d’attaque simulée, avec le nombre d’attaques passées, et un lien ou un script pour tout reproduire.

Pour comparer deux garde-fous, utilisez pour les deux les mêmes jeux, le même jour, le même matériel et la même règle de seuil, ou indiquez que les deux utilisent 0,5.

Comment nous l’appliquons à Guardrino

Guardrino, le pare-feu IA que HisnLabs construit pour les entreprises, est en développement, et sa page produit comporte une section de résultats mesurés qui reste volontairement vide. Elle n’apparaîtra qu’une fois qu’une version aura été testée exactement selon cette méthode, chaque chiffre accompagné de son n et de sa marge. D’ici là, nous décrivons ce que Guardrino est conçu pour faire, et rien de plus. Pour la conception elle-même, voyez notre guide des garde-fous IA ; pour les raisons du projet, lisez pourquoi nous construisons Guardrino pour le Moyen-Orient.

Le rôle de Guardrino et de HisnLabs

Les rapports de version de Guardrino sont prévus pour suivre chacune des règles de ce tutoriel, et sa page produit n’affiche aucun résultat tant que le premier n’existe pas. D’ici là, la simulation ci-dessous montre seulement ce que Guardrino est conçu pour faire, pas avec quelle efficacité.

Sources