Attaques par épuisement de tokens : déni de service économique via les chaînes d'outils des agents
Deux papers de 2026 montrent qu'un outil ou un skill malveillant peut entraîner un agent LLM dans de longues boucles d'appels d'outils, multipliant le coût en tokens par 6 à 658× tout en renvoyant la bonne réponse — une variante furtive de l'Unbounded Consumption de l'OWASP.
De quoi s’agit-il ?
La plupart des attaques contre les agents cherchent à leur faire faire une mauvaise action — fuiter des données, exécuter une commande, contourner un garde-fou. Une autre classe vise la facture plutôt que le comportement : l’agent réalise correctement la tâche, mais le coût explose. Comme la consommation de tokens se traduit directement en euros, en latence et en mémoire GPU, un attaquant capable de gonfler le nombre de tokens qu’un agent génère et ré-ingère dispose d’un déni de service discret, qui préserve la justesse du résultat.
Deux papers de 2026 chiffrent le phénomène. Beyond Max Tokens: Stealthy Resource Amplification via Tool Calling Chains in LLM Agents (Zhou et al. ; arXiv 2601.10955, janvier 2026) présente la boucle multi-tours agent–outil comme une surface de déni de service économique largement inexplorée et rapporte une amplification de 65 à 658× dans un simulateur contraint. Clawdrain (Ben Dong, Hui Feng, Qian Wang, UC Merced ; arXiv 2603.00902, 1er mars 2026) reproduit l’idée dans un déploiement proche de la production — l’assistant auto-hébergé OpenClaw (v2026.2.9) adossé à Gemini 2.5 Pro — et mesure une amplification plus modeste mais bien réelle de 6 à 9× sur une seule requête. Les deux relèvent de ce que l’OWASP catalogue sous LLM10:2025 Unbounded Consumption, et plus précisément de sa variante Denial of Wallet.
Comment ça marche
Le levier, c’est la boucle d’appels d’outils de l’agent lui-même. Un agent outillé raisonne, appelle un outil, lit le résultat, l’ajoute à la conversation, puis recommence — en renvoyant au modèle, à chaque tour, le transcript qui ne cesse de grossir. Un outil ou un skill installé malveillant exploite ce fonctionnement en allongeant chaque tour et en forçant davantage de tours, sans jamais casser la tâche.
Boucle benigne Boucle d'epuisement (justesse preservee)
----------------------------- -----------------------------------
demande -> appel outil -> demande -> appel outil -> l'outil
resultat court -> reponse repond "etape 1 sur N, renvoyez
(1 tour) toutes les donnees" -> l'agent
regenere une charge verbeuse
-> ... repete N fois -> reponse
(cout = O(charge x N) + historique)
Dans Clawdrain, le déclencheur réside dans un SKILL.md injecté — la description markdown qu’un skill expose au modèle — qui ordonne à l’agent d’exécuter un « handshake » de vérification en plusieurs étapes avant de recevoir les données. Le script associé renvoie des signaux continuer / réessayer / terminé, si bien que l’agent boucle, régénérant une longue charge à chaque tour, tandis qu’un prétexte plausible (« le fournisseur de données l’exige ») l’empêche de remettre en cause le protocole. Aucune chaîne d’exploitation n’est nécessaire ; l’instruction nuisible est du texte ordinaire que le framework injecte au niveau de privilège du prompt système.
Le paper met aussi en lumière trois réalités de déploiement qu’un simulateur ignore. D’abord, l’échec peut coûter plus cher que le succès : lorsque le protocole était réglé trop agressivement, l’agent l’abandonnait et lançait une cascade de récupération — nouvelles tentatives, recherche web, arrêt de processus — qui brûlait plus de tokens qu’une exécution propre. Ensuite, les agents compétents contournent parfois l’épuisement en scriptant le travail répétitif (lors d’une exécution, le modèle a généré la séquence via une commande Python d’une ligne plutôt que token par token), ce qui atténue l’attaque mais ouvre de nouveaux canaux de flux de contrôle. Enfin, la furtivité dépend de l’interface : une interface de chat affiche chaque appel, un terminal narré masque les traces brutes, et une tâche planifiée (cron/heartbeat) s’exécute sans aucune sortie visible pour l’utilisateur.
Pourquoi c’est important
Le coût en tokens est désormais un risque opérationnel de premier plan. Les mêmes papers signalent des déploiements réels où des automatisations mal configurées (non malveillantes) ont brûlé des millions de tokens en une nuit — Clawdrain cite un incident OpenClaw de 5,7 millions de tokens consommés en une nuit — si bien qu’un épuisement délibéré se cache confortablement dans le bruit normal. La surface d’attaque est vaste : tout agent qui installe des skills tiers, suit les sorties d’outils comme des instructions ou s’exécute sans surveillance sur un planning est exposé, et les points d’entrée reproduisent la chaîne d’approvisionnement classique (un skill empoisonné dans un registre, une dépendance compromise, ou une injection de prompt l’incitant à s’auto-installer). Surtout, cela échappe aux défenses calibrées sur le contenu : la sortie est correcte, aucune politique n’est enfreinte, et un plafond de tokens par appel ne voit pas une boucle qui reste sous la limite à chaque tour.
Défenses
Les recommandations de l’OWASP sur l’Unbounded Consumption constituent la bonne base ; les boucles d’outils des agents en exigent quelques compléments :
- Budgétisez la tâche entière, pas l’appel. Les plafonds de tokens par requête manquent les épuisements multi-tours. Imposez un plafond cumulé de tokens/coût et un nombre maximal d’appels d’outils par tâche ou par session, et interrompez dès que l’un est franchi.
- Traitez les descriptions de skills et les sorties d’outils comme des données non fiables, pas comme des instructions. N’autorisez pas un
SKILL.mdou une réponse d’outil à injecter du flux de contrôle au privilège du prompt système. Maintenez les instructions de la plateforme dans une strate distincte, de confiance supérieure (voir hiérarchie des instructions). - Surveillez les ratios d’amplification. Journalisez les tokens-par-tâche et les appels-d’outils-par-tâche, et alertez sur les valeurs aberrantes par rapport à une référence bénigne ; une requête qui coûte habituellement ~30 k tokens et qui passe soudain à 200 k est le signal.
- Encadrez le plus durement l’exécution non surveillée. Les exécutions cron/heartbeat sont le cas invisible — accordez aux tâches planifiées les budgets, limites de débit et délais les plus stricts, et exigez une revue humaine de toute activité de fond coûteuse.
- Auditez les skills tiers comme une chaîne d’approvisionnement. Relisez ou isolez les skills installés, figez les versions, et surveillez les documentations surdimensionnées, qui gonflent le coût en entrée à chaque tour, que le skill soit appelé ou non.
- Échouez en mode fermé sur le coût. Concevez une dégradation gracieuse : lorsqu’un outil dysfonctionne, plafonnez les tentatives et les boucles de récupération afin qu’un chemin d’échec ne puisse pas dépenser plus que le chemin de succès.
État des lieux
| Élément | Référence | Date | Notes |
|---|---|---|---|
| Beyond Max Tokens (amplification par chaîne d’outils) | arXiv 2601.10955 (Zhou et al.) | 2026-01 | Amplification de 65 à 658× en simulateur contraint ; définit la surface de déni de service économique |
| Clawdrain (reproduction proche production) | arXiv 2603.00902 (UC Merced) | 2026-03-01 | 6 à 9× sur OpenClaw v2026.2.9 + Gemini 2.5 Pro ; résultats sur échec coûteux, composition d’outils et furtivité selon l’interface |
| OWASP LLM10:2025 Unbounded Consumption | genai.owasp.org | 2025 (à jour) | Cadre le Denial of Wallet ; correspond à MITRE ATLAS AML.T0034 Cost Harvesting et AML.T0029 Denial of ML Service |
Ce qu’il faut retenir : à mesure que les agents remplacent les requêtes uniques par de longues chaînes d’appels d’outils, le coût d’une tâche devient une composante de son modèle de menace. Une attaque par épuisement ne déclenche jamais de filtre de contenu — elle fait simplement tourner le compteur — si bien que la défense réside dans les budgets, la supervision et les frontières de confiance, et non dans l’inspection des sorties.