AI Security

Appels d'outils sécurisés : Protéger les agents IA en production

À mesure que les grands modèles de langage (LLM) évoluent de simples chatbots vers des agents autonomes capables d'exécuter des tâches complexes, le mécanisme d'appel d'outils (ou appel de fonction) est devenu le pont critique entre l'inférence et l'action. Cependant, ce pouvoir introduit une surface d'attaque significative. Si un LLM est compromis, l'attaquant peut invoquer des outils arbitraires, entraînant une exfiltration de données, une modification du système ou une prise de contrôle totale. Cet article explore les meilleures pratiques pour sécuriser les pipelines d'appel d'outils, en allant au-delà du simple ingénierie de prompts pour atteindre des contrôles architecturaux robustes.

Le modèle de menace : Pourquoi les appels d'outils sont vulnérables

Contrairement au code statique, les LLM sont probabilistes. Lorsqu'un LLM reçoit une entrée utilisateur, il génère un objet JSON destiné à un outil backend. La vulnérabilité réside dans la limite de confiance : nous faisons souvent confiance implicitement à la sortie du LLM. Un attaquant utilisant une injection de prompt indirecte peut manipuler le modèle pour générer des paramètres d'outil malformés ou malveillants. Par exemple, un e-mail malveillant pourrait contenir du texte qui amène le LLM à appeler un outil send_email avec une adresse cible contrôlée par l'attaquant.

Principe 1 : Validation stricte des schémas

La première ligne de défense consiste à ne jamais faire confiance directement à la sortie du LLM. Vous devez imposer des schémas stricts (par exemple, JSON Schema, Pydantic) avant de transmettre des arguments à n'importe quelle fonction backend. Cela garantit que les entrées sont du bon type, de la bonne longueur et du bon format, empêchant ainsi les tentatives d'injection de base et les erreurs de confusion de type.

Considérez l'exemple Python suivant utilisant Pydantic pour la validation :

import json
from pydantic import BaseModel, field_validator

class TransferMoneySchema(BaseModel):
    recipient: str
    amount: float
    currency: str

    @field_validator('recipient')
    def validate_recipient(cls, v):
        # S'assurer que le destinataire n'est pas un chemin de fichier malveillant ou une commande
        if ".." in v or "/" in v:
            raise ValueError("Format de destinataire invalide")
        return v

def execute_tool_call(raw_json: str):
    try:
        # Étape 1 : Analyser le JSON en toute sécurité
        data = json.loads(raw_json)
        
        # Étape 2 : Valider selon le schéma
        # Cela génère une ValidationError si les données sont malveillantes ou malformées
        validated_data = TransferMoneySchema(**data)
        
        # Étape 3 : Exécuter uniquement si la validation réussit
        process_transfer(validated_data.recipient, validated_data.amount)
    except (json.JSONDecodeError, ValidationError) as e:
        log_security_event(f"Appel d'outil invalide rejeté : {e}")

Principe 2 : Principe du moindre privilège et autorisations

Comme dans la sécurité traditionnelle des logiciels, les agents IA doivent fonctionner selon le principe du moindre privilège. Si un agent a besoin de lire les e-mails des utilisateurs mais pas de les supprimer, le jeton API sous-jacent ou la portée de la fonction ne doit pas accorder de permissions de suppression. De plus, envisagez de mettre en œuvre des étapes de confirmation par l'utilisateur pour les actions à haut risque (par exemple, transactions financières, suppressions irréversibles).

Principe 3 : Sanitisation des entrées et des sorties

Au-delà de la validation des schémas, sanitizez les entrées au niveau de l'application. Pour les outils qui interagissent avec des bases de données ou des systèmes de fichiers, utilisez des requêtes paramétrées et empêchez l'injection de commandes OS. Côté sortie, assurez-vous que les données récupérées par les outils ne divulguent pas involontairement d'informations sensibles au LLM, qui pourrait ensuite les exposer à l'utilisateur.

Conclusion

Sécuriser les appels d'outils n'est pas une configuration ponctuelle, mais un processus continu nécessitant des défenses en couches. En combinant une validation stricte des schémas, des contrôles d'accès au moindre privilège et une sanitisation rigoureuse, les développeurs peuvent exploiter la puissance des agents LLM sans exposer leur infrastructure à des risques excessifs. À mesure que le paysage de la sécurité IA évolue, rester vigilant face aux nouvelles techniques d'injection et mettre à jour votre logique de validation en conséquence sera essentiel pour maintenir la confiance dans les systèmes IA autonomes.

Share: