Home » AI » Comment sécuriser le tool calling avec Gemma 4 ?

Comment sécuriser le tool calling avec Gemma 4 ?

En cloisonnant les outils locaux, Gemma 4 peut lire des fichiers et exécuter du Python sans devenir dangereux. L’enjeu n’est pas le tool calling lui-même, mais les droits accordés au modèle, la sandbox, la validation des chemins et les garde-fous d’exécution.

Quand un chatbot devient-il un agent ?

Un chatbot devient agent quand il peut observer son environnement, choisir une action, l’exécuter via un outil, puis intégrer le résultat dans son raisonnement. La différence n’est donc pas marketing, elle est opérationnelle : le système ne se contente plus de répondre, il agit dans une boucle.

Un chatbot classique travaille surtout à partir de la conversation. Il lit votre message, produit une réponse, puis attend la suite. Un assistant connecté va plus loin : il peut appeler une API, c’est-à-dire une interface de programmation applicative, souvent pour lire une donnée externe comme une météo, un prix ou un statut de commande. Un agent local franchit un seuil supplémentaire lorsqu’il peut inspecter un système de fichiers, lancer un script, interroger une base locale ou modifier un état.

Chatbot Répond à partir du contexte de conversation, sans action externe.
Assistant avec API Demande une donnée à un service externe, généralement en lecture seule.
Agent local Observe un environnement, choisit une action, appelle un outil, puis vérifie le résultat.

Le tool calling désigne cette méthode : le modèle ne clique pas, ne lance pas de commande et n’accède pas directement à la machine. Il produit une requête structurée, souvent en JSON, un format texte clé-valeur lisible par les machines, pour demander l’exécution d’une fonction externe. Ensuite, l’orchestrateur décide si l’appel est autorisé, avec quels paramètres, dans quelles limites, et comment le résultat est renvoyé au modèle.

Le terme agentique décrit cette capacité à enchaîner observation, décision, action et vérification. C’est puissant, mais c’est aussi là que le risque apparaît. L’OWASP Top 10 for LLM Applications classe l’excessive agency parmi les risques majeurs des applications basées sur des LLM, car trop de permissions données à un agent peuvent produire des actions non souhaitées : suppression de fichiers, appels réseau abusifs, fuite de données ou modification d’un système sans validation humaine.

Avec Gemma 4 dans une architecture locale, l’objectif n’est donc pas de donner les clés du poste hôte au modèle. L’objectif est de lui permettre d’interagir avec son environnement à travers des outils limités, explicites et contrôlés. Si l’agent ne doit pas exécuter lui-même, il faut une boucle d’orchestration claire, contrôlée et auditable.

Quelle architecture garder pour le tool calling ?

L’architecture à garder est une boucle d’orchestration stable qui déclare les fonctions disponibles, expose leur schéma JSON au modèle, intercepte les tool_calls, exécute localement la fonction autorisée, puis réinjecte le résultat dans la conversation avec un rôle tool.

Le point important est simple : Gemma 4 ne doit pas exécuter directement une action. Le modèle produit une intention structurée, par exemple “appeler telle fonction avec tels paramètres”. Votre application garde la main sur l’exécution réelle.

Le flux logique reste toujours le même :

  • Définir une fonction Python classique, par exemple une fonction get_weather(city) qui récupère la météo d’une ville.
  • Décrire ses paramètres dans un schéma JSON, c’est-à-dire un contrat lisible par le modèle qui précise les champs attendus, leurs types et les valeurs obligatoires.
  • Transmettre cette liste d’outils au modèle avec leurs noms, descriptions et schémas.
  • Laisser Gemma 4 demander un appel d’outil via un tool_call, sans considérer cette demande comme une décision finale.
  • Vérifier côté application que l’outil demandé est bien autorisé, que les paramètres sont valides et que l’utilisateur a le droit de déclencher cette action.
  • Exécuter localement la fonction autorisée, dans votre code, avec vos règles de sécurité.
  • Renvoyer le résultat au modèle avec un rôle tool, pour qu’il puisse continuer son raisonnement et formuler une réponse utile.

Cette séparation évite une erreur fréquente : traiter le modèle comme une autorité d’exécution. Il ne l’est pas. Il propose une action sous forme structurée, mais votre application décide, filtre, journalise et exécute.

Avec des outils agentiques locaux, la boucle ne change pas. Le risque, lui, change fortement. Une API météo en lecture seule expose peu de surface dangereuse. Un accès au système de fichiers ou à un interprète Python peut lire, modifier ou produire des données sensibles si le périmètre n’est pas strictement contrôlé.

Type d’outil Exemple Niveau de risque
API en lecture seule API météo en lecture seule Faible
Accès local limité Explorateur de fichiers sandboxé Moyen à élevé
Exécution de code Interprète Python restreint Élevé

La première barrière concrète consiste donc à cloisonner le système de fichiers, pour que même un appel d’outil valide ne puisse jamais sortir du périmètre prévu.

Comment enfermer l’exploration de fichiers ?

L’exploration de fichiers doit être enfermée dans un répertoire de base sûr, défini au démarrage, et toute tentative de sortie de ce répertoire doit être refusée. SAFE_BASE_DIR représente cette frontière : c’est la seule zone que l’agent Gemma 4 peut inspecter via un tool calling.

Le modèle peut demander un chemin relatif, par exemple logs/ ou data/input.csv. L’application ne doit jamais faire confiance à ce chemin tel quel. Un chemin comme ../ peut tenter de remonter dans l’arborescence, et un chemin absolu comme /etc/passwd peut viser directement un fichier sensible. La protection consiste à combiner le chemin demandé avec SAFE_BASE_DIR, calculer son chemin absolu avec os.path.abspath, puis vérifier qu’il reste bien sous la zone autorisée.

import os

SAFE_BASE_DIR = os.path.abspath("./safe_workspace")

def list_directory_contents(path=""):
    requested_path = path or ""

    target_path = os.path.abspath(
        os.path.join(SAFE_BASE_DIR, requested_path)
    )

    if os.path.commonpath([SAFE_BASE_DIR, target_path]) != SAFE_BASE_DIR:
        return {"error": "Accès refusé : chemin hors du répertoire autorisé."}

    if not os.path.isdir(target_path):
        return {"error": "Chemin introuvable ou dossier invalide."}

    return {
        "path": target_path,
        "files": os.listdir(target_path)
    }

Les points importants sont simples, mais ils évitent beaucoup d’erreurs classiques.

  • SAFE_BASE_DIR est résolu avec os.path.abspath dès le démarrage, pour travailler avec une référence stable et absolue.
  • Le chemin demandé par le modèle reste une entrée non fiable, même s’il vient d’un appel d’outil structuré.
  • La fonction os.path.join combine la base autorisée et la demande du modèle, puis os.path.abspath normalise le résultat en supprimant les ambiguïtés comme ../.
  • La fonction os.path.commonpath vérifie l’appartenance réelle au répertoire autorisé, sans se faire piéger par des préfixes trompeurs comme /safe et /safe_but_not_really.
  • Le refus retourne une erreur contrôlée, au lieu de laisser l’outil exposer une exception ou un contenu sensible.

Ce mécanisme reste un garde-fou applicatif. Il ne remplace pas une isolation système, comme un conteneur, des permissions Unix restrictives ou un environnement d’exécution séparé. Lire des fichiers est déjà sensible, mais exécuter du code avec un interpréteur Python l’est encore plus.

Comment limiter un interprète Python local ?

Un interprète Python local doit être considéré comme un outil à haut risque et limité par défaut. L’exécution de code transforme l’agent en acteur capable de produire des effets sur la machine : consommation CPU, accès mémoire, lecture ou écriture de fichiers, appels réseau, lecture des variables d’environnement et utilisation des dépendances installées.

Le but n’est donc pas de donner un Python libre au modèle, mais une surface d’exécution contrôlée. Les documentations Python alertent depuis longtemps sur les risques liés à l’exécution de code non fiable avec eval ou exec. Une chaîne produite par un modèle ne doit jamais être exécutée directement sans contrôle, même si elle “semble” simple.

Les garde-fous doivent être pensés comme des couches complémentaires :

  • Limiter les modules importables, par exemple à math, statistics ou json, et refuser os, subprocess, socket, pathlib ou requests.
  • Bloquer le réseau, car un agent ne doit pas pouvoir exfiltrer des données ou appeler une API externe sans autorisation explicite.
  • Interdire ou filtrer les opérations fichiers, surtout l’accès aux chemins sensibles comme /etc, le répertoire utilisateur ou les clés SSH.
  • Imposer un timeout court, par exemple 1 à 3 secondes, pour éviter les boucles infinies et la saturation CPU.
  • Limiter la taille des entrées et sorties, afin d’éviter les charges mémoire ou les réponses gigantesques.
  • Exécuter dans un processus séparé, avec un environnement minimal et sans secrets.
  • Journaliser les appels, le code exécuté, la durée, la sortie standard, les erreurs et la décision de blocage.
  • Retourner des erreurs explicites, pour que l’agent comprenne ce qui est interdit sans contourner la règle.
def run_python_safely(code: str) -> dict:
    allowed_modules = {"math", "statistics", "json"}

    if len(code) > 5_000:
        return {"ok": False, "error": "Code trop long"}

    # Analyse simplifiée des imports avant exécution.
    tree = ast.parse(code)
    for node in ast.walk(tree):
        if isinstance(node, (ast.Import, ast.ImportFrom)):
            names = [alias.name.split(".")[0] for alias in node.names]
            if any(name not in allowed_modules for name in names):
                return {"ok": False, "error": "Module non autorisé"}

    with tempfile.TemporaryDirectory() as workdir:
        script = Path(workdir) / "task.py"
        script.write_text(code, encoding="utf-8")

        result = subprocess.run(
            [sys.executable, "-I", str(script)],
            cwd=workdir,
            env={},                 # Pas de secrets exposés.
            capture_output=True,
            text=True,
            timeout=2               # Coupe les exécutions longues.
        )

    return {
        "ok": result.returncode == 0,
        "stdout": result.stdout[:4_000],
        "stderr": result.stderr[:4_000]
    }

Ce code reste conceptuel. Pour un usage sérieux avec Gemma 4 ou n’importe quel agent, l’isolation doit idéalement se faire au niveau système : conteneur verrouillé, environnement jetable, utilisateur sans privilèges, réseau désactivé, quotas CPU et mémoire.

Plus l’outil peut modifier l’environnement, plus il faut réduire ses permissions et augmenter l’observabilité.

Quels garde-fous mettre en production ?

En production, la sécurité d’un agent Gemma 4 repose sur le principe du moindre privilège, des outils explicitement autorisés et une traçabilité complète des actions.

Une sandbox de fichiers et un interpréteur restreint réduisent la surface d’attaque, mais ils ne suffisent pas seuls. Il faut une politique d’exécution globale, c’est-à-dire un ensemble de règles qui décident quels outils l’agent peut appeler, avec quels paramètres, dans quel environnement, pendant combien de temps, et sous quelle supervision.

La checklist opérationnelle doit rester simple, testable et appliquée côté serveur, pas seulement dans le prompt système.

  • Définir une allowlist d’outils. Une allowlist est une liste fermée d’outils autorisés. Tout ce qui n’est pas dedans est refusé par défaut.
  • Refuser tout outil inconnu. Un tool_call vers une fonction non déclarée doit échouer, même si le modèle le formule correctement.
  • Valider strictement les arguments JSON. Le JSON doit respecter un schéma précis : types, champs obligatoires, longueurs maximales, formats attendus.
  • Fixer des limites de temps et de volume. Un appel outil doit avoir un timeout, une taille maximale d’entrée, une taille maximale de sortie et, si besoin, un quota par utilisateur.
  • Isoler les environnements. Les outils sensibles doivent tourner dans des conteneurs, comptes ou machines séparés, avec des droits minimaux.
  • Ne jamais exposer de secrets dans le contexte. Les clés API, tokens, mots de passe et variables d’environnement ne doivent pas être visibles par le modèle.
  • Journaliser chaque tool_call. Il faut conserver l’outil appelé, les arguments validés, l’utilisateur, l’heure, le résultat et les erreurs.
  • Tester les chemins malveillants. Les valeurs comme ../, /etc/passwd ou des chemins absolus doivent être bloquées et couvertes par des tests automatisés.
  • Prévoir une validation humaine. Toute action destructrice, coûteuse ou irréversible doit passer par une confirmation humaine.
  • Surveiller les erreurs récurrentes. Des refus répétés, des arguments invalides ou des tentatives hors périmètre peuvent signaler une attaque ou un mauvais design.

Cette logique rejoint les recommandations de l’OWASP Top 10 for LLM Applications, notamment sur les appels d’outils excessifs, les fuites de données et les contrôles d’autorisation. Elle s’aligne aussi avec le NIST AI Risk Management Framework, qui insiste sur la gouvernance, la supervision, la mesure des risques et leur réduction continue.

Sortie de sandbox Un chemin contient ../ pour remonter dans l’arborescence. Normaliser les chemins et bloquer toute sortie du répertoire autorisé. Les fichiers hors périmètre restent inaccessibles.
Exécution de code dangereuse Un outil tente de lancer une commande système non prévue. Limiter l’interpréteur, désactiver les appels système risqués et appliquer un timeout. L’agent peut calculer sans devenir un shell ouvert.
Fuite de secret Une clé API est injectée dans le contexte du modèle. Stocker les secrets côté serveur et ne transmettre que des identifiants temporaires. Le modèle ne peut pas révéler ce qu’il ne voit pas.
Action non voulue Un agent supprime une ressource après une mauvaise interprétation. Demander une validation humaine pour les actions destructrices. L’autonomie reste contrôlée avant impact réel.

L’objectif n’est pas de brider l’agent, mais de rendre son autonomie exploitable dans un cadre maîtrisé, compréhensible et vérifiable.

Alors, jusqu’où laisser agir Gemma 4 ?

Gemma 4 peut devenir beaucoup plus utile avec du tool calling agentique, à condition de ne pas confondre autonomie et accès illimité. La bonne approche consiste à garder une orchestration simple : le modèle demande, l’application vérifie, l’outil exécute, puis le résultat revient dans la conversation. Pour les fichiers, je limite l’accès à un répertoire sandboxé. Pour Python, je réduis fortement les permissions, le temps d’exécution et les sorties. En production, j’ajoute logs, allowlist, tests et validation humaine si nécessaire. Le bénéfice pour vous : des agents locaux plus puissants, mais contrôlables et auditables.

FAQ

  • Qu’est-ce que le tool calling avec Gemma 4 ?
    Le tool calling permet à Gemma 4 de demander l’exécution d’une fonction externe avec des arguments structurés, souvent en JSON. Le modèle ne lance pas directement l’action : l’application intercepte la demande, vérifie qu’elle est autorisée, exécute l’outil localement, puis renvoie le résultat au modèle.
  • Pourquoi parler d’agent plutôt que de chatbot ?
    Un chatbot répond principalement à partir de la conversation. Un agent observe un environnement, décide d’une action, utilise un outil, puis raisonne à partir du résultat. Dès qu’un modèle peut explorer des fichiers ou exécuter du code, il faut raisonner en termes d’agent et de permissions.
  • Comment sécuriser l’accès aux fichiers ?
    Je fixe un répertoire de base sûr, par exemple SAFE_BASE_DIR, puis je refuse tout chemin résolu qui sort de cette zone. Les chemins relatifs comme ../ et les chemins absolus doivent être contrôlés avant toute lecture. L’agent ne doit voir que ce qui est explicitement autorisé.
  • Un interprète Python local est-il dangereux ?
    Oui, s’il est exposé sans restriction. Exécuter du Python peut donner accès au système de fichiers, au réseau, aux variables d’environnement ou consommer trop de ressources. Il faut donc limiter les modules, bloquer les accès inutiles, imposer des timeouts et isoler l’exécution autant que possible.
  • Quels sont les garde-fous minimum en production ?
    Il faut une allowlist d’outils, une validation stricte des arguments, des limites de temps et de taille, une sandbox, des logs détaillés, aucun secret dans le contexte et, pour les actions sensibles, une validation humaine. Le principe de base reste le moindre privilège.

 

 

A propos de l’auteur

Je suis Franck Scandolera, responsable de l’agence webAnalyste et de l’organisme Formations Analytics. J’accompagne les entreprises sur le tracking avancé server-side, l’Analytics Engineering, l’automatisation No/Low Code avec n8n, l’intégration de l’IA dans les process business et le SEO/GEO. J’ai travaillé pour des références comme Logis Hôtel, Yelloh Village, BazarChic, la Fédération Française de Football ou Texdecor. Si vous voulez cadrer un projet IA, automatisation ou data sans perdre le contrôle technique, contactez-moi.

Retour en haut
ClickAIpro