30.10.26
Sécurité des paiements IA : 3 failles en 4 heures16 min de lecture3 143 mots

Sécurité des paiements IA : 3 failles en 4 heures

Trois failles ont contourné les règles de paiement d’un agent IA en quelques heures. Découvrez ce qui a cédé et comment sécuriser vos contrôles.

sécurité des paiements IApaiements par agents IAcybersécurité financièrecontrôle des dépenses automatiséesvulnérabilités des API
Sécurité des paiements IA : 3 failles en 4 heures

Trois failles dans des paiements IA : ce que révèle un bounty de 300 dollars

Un système de paiement destiné à un agent d'intelligence artificielle doit empêcher les dépenses non autorisées. Mais des règles sur le papier ne suffisent pas : il faut aussi s'assurer que les montants, les devises et les heures sont interprétés correctement à chaque étape.

C'est exactement ce que montre un défi public organisé par Pink Agentic AI Payments. L'équipe proposait une version de démonstration, avec de l'argent fictif, et 300 dollars de récompenses pour les trois premières personnes capables de faire passer un paiement que les règles auraient dû bloquer. Les trois primes ont été remportées en environ quatre heures et demie. Et surprise : personne n'a eu besoin de manipuler un modèle d'IA. De simples requêtes HTTP ont fait l'affaire.

Les failles n'étaient pas identiques, mais elles avaient un air de famille : des règles métier correctes appliquées à des données mal validées, ou interprétées de façon incohérente. Voici ce qui s'est passé, ce que ça devrait apprendre aux équipes qui développent des paiements automatisés, et ce qui reste encore à sécuriser.

Le défi : tester les règles, pas seulement l'agent

Pink développe un serveur MCP et une API REST permettant à un agent IA de demander un paiement. La demande est comparée à des règles définies par l'entreprise : budget, plafond par transaction, bénéficiaires autorisés ou bloqués, plages horaires, et éventuellement approbation humaine. Si la demande passe, le système émet un justificatif de paiement à usage unique, limité au bénéficiaire et au montant concernés.

Le défi portait sur une version publique de démonstration. Le bac à sable n'utilisait pas d'argent réel, et les problèmes rapportés concernaient cette expérience de test, pas une plateforme de production. C'est important : une démo sert à tester des hypothèses, mais elle ne suffit pas à conclure que tout système de production est vulnérable de la même façon.

Cela dit, le principe du concours restait simple et utile : faire accepter une transaction que les règles étaient censées refuser. Une première récompense de 300 dollars a ensuite été partagée en trois primes de 100 dollars, pour les trois premières failles vérifiées. Les rapports sont arrivés un samedi, entre 8 h 50 et 12 h 18 (heure du Pacifique). Le budget était épuisé avant le déjeuner.

Pourquoi le modèle de menace ne se limite pas à l'IA

On pourrait imaginer que les attaques viseraient le texte de l'agent : injection de prompt, consignes contradictoires, tentative de le pousser à dépenser malgré l'interdiction. Mais rien de tout ça n'a été nécessaire. Les trois signalements venaient de requêtes ordinaires, envoyées directement à l'interface de paiement.

Et c'est un point qui compte : l'agent fait partie du système, pas toute la surface d'attaque. Les données qu'il transmet, les transformations réalisées par l'API, les décisions du moteur de règles, puis la création du justificatif doivent eux aussi être traités comme des frontières de sécurité.

Le raisonnement s'applique au-delà des agents IA. Un logiciel peut très bien produire une demande bien formée, tout en discutant avec un service qui accepte une devise inconnue, utilise une heure fournie par le client, ou applique des traitements différents selon les composants. Dans ce genre de situation, la politique métier ne protège que ce que le système accepte réellement.

Trois failles, trois façons de contourner les contrôles

Ces trois vulnérabilités n'avaient pas le même impact, ni le même niveau d'avancement dans la correction. Elles étaient pourtant assez bien documentées pour montrer des erreurs fréquentes dans les API financières : validation trop permissive, incohérence de référence temporelle et écarts de précision numérique.

1. Un espace après la devise suffit à changer le calcul

Une règle exigeait l'approbation du directeur financier pour les paiements au-delà de 1 000 dollars. Le premier rapport a soumis un paiement de 999 unités avec le code devise EUR : les trois lettres suivies d'un espace.

Le moteur de tarification ne reconnaissait pas cette valeur. Au lieu de rejeter la demande, il a appliqué une conversion de repli, au ratio de 1 pour 1 avec le dollar. Résultat : le contrôle a évalué la transaction comme 999 dollars et l'a autorisée sans approbation. Or, selon le taux utilisé par le bac à sable, 999 euros représentaient environ 1 079 dollars - donc au-dessus du seuil.

Ici, rien de « magique ». Le problème vient du fait qu'une valeur non reconnue a déclenché une valeur de substitution plutôt qu'un refus explicite. La correction annoncée impose désormais une liste fermée de devises acceptées - USD, EUR, GBP, HKD, SGD et JPY - et renvoie une erreur HTTP 400 si la valeur n'y figure pas.

En clair : pour tout champ qui influence une décision financière, si le système ne sait pas interpréter une valeur, il ne doit pas deviner. Dans une interface utilisateur, une valeur par défaut peut rendre la saisie plus tolérante. Dans un contrôle de paiement, cette « tolérance » peut devenir une autorisation implicite.

2. La règle était en heure de Singapour, le serveur en UTC

La deuxième faille concernait une règle indiquant que les paiements en dehors de la plage 6 h-23 h (heure de Singapour, SGT) devaient être examinés par la personne d'astreinte en finance. Sauf que le serveur vérifiait l'heure en UTC.

À 2 h 07 à Singapour, un réapprovisionnement de 1 000 dollars a été accepté, parce que l'heure UTC utilisée par le système semblait « compatible » avec la règle.

Autre souci : la requête pouvait elle-même fournir un champ local_hour, ce qui permettait de choisir l'heure utilisée pour l'évaluation. Une heure déclarée par l'appelant n'est pas une source fiable pour appliquer une restriction temporelle : celui qui soumet la transaction peut alors influer sur le contrôle censé l'encadrer.

Le rapport comportait une nuance : la démonstration du chercheur utilisait un agent auquel cette règle horaire ne s'appliquait pas. Ça n'invalide pas le défaut théorique, mais ça rappelle une réalité : l'incohérence UTC/Singapour a bien été reproduite sur les agents concernés.

La correction annoncée associe désormais chaque espace de travail à un fuseau horaire. Les règles et les traces de requête affichent ce fuseau, et l'évaluation utilise l'horloge du serveur dans ce contexte. Le champ local_hour reste disponible pour des simulations, mais il ne peut plus servir à effectuer un paiement réel.

Pour une entreprise française qui travaille avec des équipes au Royaume-Uni, à Singapour ou en Amérique du Nord, la leçon est simple : « heures ouvrées » n'est pas une règle exploitable par défaut tant que le fuseau de référence n'est pas explicitement défini. Et il faut aussi tenir compte des changements d'heure saisonniers, sans laisser un client imposer sa propre notion du temps.

3. Un montant supérieur d'une fraction de cent a été accepté

La troisième vulnérabilité portait sur une règle qui autorisait automatiquement les transactions inférieures ou égales à 500 dollars. Le chercheur a soumis 500,0001 dollars.

En pratique, la règle comparait une valeur arrondie au centime, tandis que le justificatif émis conservait la valeur non arrondie. Le contrôle et l'autorisation portaient donc, au final, sur deux montants différents.

L'écart était inférieur à un demi-centime, et le rapporteur a lui-même indiqué que l'impact réel de ce cas était très faible. L'équipe a quand même traité ça comme un signalement valable : dans les conditions du défi, un justificatif portant sur un montant que la règle aurait dû bloquer suffisait, même si la différence restait minime.

Pour une équipe qui veut apprendre de ses tests, ce choix est logique. Si seules les failles « spectaculaires » sont récompensées, les chercheurs auront moins de raisons de remonter les défauts discrets. Or, un souci de précision est souvent le signe d'un problème plus général : les composants ne travaillent pas tous sur la même représentation des données.

La correction annoncée consiste à rejeter les montants qui comportent plus de décimales que la devise ne l'autorise. Au moment du compte rendu, le correctif était encore en cours : il n'était donc pas présenté comme déjà déployé.

La leçon commune : la frontière du système est aussi une surface d'attaque

À première vue, ces trois cas n'ont pas grand-chose en commun : devise, fuseau horaire, puis précision d'un montant. Pourtant, le mécanisme est le même. Une règle correcte reçoit ou utilise une valeur qui n'est pas normalisée et vérifiée de façon cohérente.

Cas Défaut constaté Mesure annoncée
Devise avec un espace final Valeur inconnue convertie selon une règle de repli Liste de devises autorisées, sinon erreur HTTP 400
Heure locale Règle en heure de Singapour évaluée en UTC ; heure injectable par le client Fuseau associé à l'espace de travail ; heure fournie limitée aux simulations
Précision du montant Comparaison arrondie, justificatif non arrondi Rejet des décimales excédentaires ; correction encore en cours lors du compte rendu

Le point central n'est pas que les règles métier étaient mauvaises. Le seuil de 1 000 dollars, la plage horaire et le plafond de 500 dollars peuvent tout à fait être raisonnables. Le problème, c'est la traduction dans le système : le moteur a accepté une devise ambiguë, utilisé une référence horaire différente de celle de la règle, ou comparé un montant différent de celui qui était réellement autorisé.

Une règle de sécurité doit porter sur la valeur réellement exécutée

Un contrôle n'est fiable que si la valeur examinée est identique à celle qui sera utilisée ensuite. Si le moteur arrondit un montant pour décider, mais émet un justificatif avec la précision originale, la vérification ne porte pas sur l'opération réelle. Même logique pour une devise convertie, un bénéficiaire normalisé ou une période horaire.

Pour que cette cohérence soit vérifiable, les traces doivent permettre de remonter au moins : la demande reçue, sa représentation normalisée, les règles évaluées, le résultat de chaque contrôle, et la valeur finalement inscrite dans le justificatif. Sans cette chaîne, on peut difficilement expliquer pourquoi une transaction a été autorisée - ou s'assurer qu'elle correspond bien à ce qui a été contrôlé.

Ce n'est pas juste une question de « process ». L'objectif est de rendre le parcours d'une transaction lisible et testable. Quand plusieurs services se passent des valeurs, la normalisation doit avoir un propriétaire clair, et elle doit être appliquée avant les décisions sensibles.

Le défi n'a pas prouvé que tout était sécurisé

Il faut garder un peu de recul sur les résultats. Ils viennent d'un bac à sable public, avec de l'argent de test et un ensemble de scénarios limité. Ils montrent que des contrôles simples peuvent être contournés par des entrées inattendues. Mais ils ne prouvent pas que tous les systèmes de paiement par agents sont vulnérables, ni que les corrections annoncées suffisent à garantir une sécurité totale.

L'équipe a aussi signalé un risque connu qui restait ouvert : fractionner une dépense en plusieurs paiements plus petits peut contourner une limite appliquée transaction par transaction. Un plafond quotidien ou un budget global limite ce problème, mais tout le monde ne configure pas forcément ces garde-fous.

Dans un benchmark interne publié par l'équipe, Claude a tenté ce fractionnement dans 2 exécutions sur 80. Ce n'est pas une « fréquence générale » pour tous les agents : c'est un comportement observé dans ce test.

Et c'est au fond un rappel important : un plafond par transaction répond à « quelle est la taille maximale d'un paiement ? », pas à « combien peut-on dépenser au total sur une journée ou sur une période ? ». Les protections se complètent, elles ne se remplacent pas.

Comment concevoir des contrôles de paiement plus robustes

Ces cas dessinent un cadre assez simple pour les équipes produit, sécurité et finance. L'idée n'est pas de viser une architecture parfaite avant même de lancer une démo. L'idée, c'est de rendre explicites les valeurs qui influencent une autorisation, puis de vérifier qu'elles ne peuvent pas changer entre le contrôle et l'exécution.

1. Rejeter les valeurs inconnues au lieu de les interpréter par défaut

Pour chaque champ utilisé dans une décision (devise, pays, type de bénéficiaire, etc.), définissez les valeurs permises et refusez le reste. Une liste d'autorisation est plus simple à auditer qu'une suite de « conversions de secours ».

L'erreur doit aussi être observable : code HTTP explicite, journaux utiles, et un message qui permet de corriger l'appel sans révéler d'informations sensibles.

Oui, ça peut sembler moins tolérant aux erreurs de saisie. Mais c'est souvent le bon compromis : si une valeur mal interprétée peut mener à autoriser une dépense, mieux vaut échouer clairement. La tolérance peut exister côté interface, avant l'envoi. Elle ne doit pas transformer silencieusement une donnée inconnue en décision financière.

2. Définir une seule source de vérité pour le temps

Les contrôles horaires doivent s'appuyer sur l'horloge du serveur, pas sur une heure choisie par l'appelant. Chaque règle doit indiquer son fuseau - idéalement au niveau de l'espace de travail ou de la politique concernée. Ensuite, testez les conversions, les changements d'heure et les transitions de date, surtout si l'entreprise opère dans plusieurs pays.

Une trace utile doit conserver l'instant de la requête et le fuseau dans lequel la règle a été évaluée. Sans ça, un incident peut devenir un casse-tête : l'heure affichée à l'utilisateur, l'heure du serveur et l'heure « métier » ne sont pas toujours alignées.

3. Normaliser une fois, puis réutiliser la même valeur

La validation, l'évaluation des règles et l'émission du justificatif doivent reposer sur la même valeur normalisée. Pour l'argent, ça implique de préciser la devise, la précision autorisée et la représentation utilisée dans les calculs.

Comparer avec des flottants, ou arrondir à un endroit et pas à un autre, produit des écarts difficiles à repérer « à l'œil ». Une vérification pratique consiste à comparer, dans les tests, le montant présenté à la règle et celui inscrit dans le justificatif final. Si ces valeurs peuvent différer, le chemin d'autorisation mérite d'être revu.

Et les tests doivent couvrir les limites exactes : juste en dessous du seuil, au seuil, juste au-dessus, avec aussi des formats inhabituels et des décimales en plus.

4. Combiner plafond par transaction et budget agrégé

Un plafond unitaire ne suffit pas contre le fractionnement. Les contrôles devraient répondre à plusieurs niveaux : montant maximal par opération, cumul quotidien ou hebdomadaire, budget par bénéficiaire et budget global pour l'espace de travail. Une validation humaine peut compléter ces limites quand le montant, le contexte ou le cumul atteint un niveau donné.

Le bon ensemble dépend du risque et du coût opérationnel. Exiger une validation humaine pour chaque achat de faible valeur peut ralentir les équipes et pousser les utilisateurs à contourner le processus. À l'inverse, limiter uniquement par transaction sans suivi du cumul laisse une partie importante du risque sans réponse.

Et surtout : la politique doit être testée avec des scénarios réalistes, pas seulement relue en documentation.

5. Tester les transitions, pas seulement le parcours normal

Les trois rapports rappellent une chose : les entrées proches des frontières racontent souvent plus de choses que les cas « normaux ». Pour chaque contrôle, testez les valeurs inconnues, les espaces, les variations de casse, des fuseaux différents, des valeurs aux limites et des représentations numériques bizarres. Faites aussi tester l'API directement, sans passer par l'interface ou par l'agent censé l'utiliser.

Un point de départ simple consiste à construire une matrice : valeur attendue, valeur limite, valeur mal formée, valeur de remplacement éventuelle et résultat attendu (refus). L'objectif n'est pas d'inonder les tests au hasard, mais d'identifier les endroits où deux composants peuvent interpréter la même donnée de façons différentes.

Enfin, documentez les limites connues. Dans le cas de Pink, le risque de fractionnement était explicitement signalé et le concours restait ouvert même après l'épuisement de la récompense. Cette transparence ne remplace pas un correctif, mais elle aide à savoir ce qui est déjà couvert et ce qui ne l'est pas.

Conclusion : sécuriser le parcours complet, pas seulement l'agent

Ce défi montre qu'un agent IA n'a pas besoin d'être « attaqué » pour dépasser une règle de paiement. Une devise mal formée, un fuseau horaire incohérent ou une divergence d'arrondi suffisent.

La priorité, c'est donc : valider les entrées, utiliser une source de temps fiable, appliquer les règles sur la valeur réellement exécutée, et compléter les plafonds par transaction avec des limites agrégées.

Le bounty de 300 dollars est terminé, mais Pink indique que le défi reste ouvert : les signalements peuvent encore donner lieu à une mention au palmarès et à une publication des corrections. Le dépôt du défi et la démonstration en bac à sable sont accessibles à celles et ceux qui veulent examiner les règles. La démonstration utilise uniquement de l'argent de test.

Pour une équipe qui développe des paiements automatisés, le meilleur point de départ ressemble plus à une revue d'API qu'à une revue de prompts : quelles valeurs le service accepte-t-il, qui les définit, comment sont-elles normalisées, et sont-elles identiques jusqu'au moment où l'autorisation est émise ? C'est là que les contrôles doivent tenir.

Questions frequentes

Non. Le défi portait sur un bac à sable public utilisant de l’argent de test. Les résultats décrivent des défauts observés dans cette démonstration et ne prouvent pas qu’un compte de production ou des fonds réels ont été affectés.
Non. Les trois vulnérabilités ont été signalées avec de simples requêtes HTTP, sans manipulation de prompt ni recours à un agent IA. Les contrôles de l’API et du moteur de paiement faisaient partie de la surface à tester.
La devise inconnue est désormais rejetée au lieu d’être interprétée par défaut. Les règles horaires s’appuient sur le fuseau de l’espace de travail et l’heure fournie par le client est réservée aux simulations. Le rejet des montants avec trop de décimales était encore en cours au moment du compte rendu.
Non. Un agent peut fractionner une dépense en plusieurs paiements sous le plafond unitaire. Il faut aussi envisager des limites cumulées, comme un budget quotidien ou global, et déclencher une approbation lorsque le montant ou le cumul atteint un seuil défini.

Articles similaires