10 points par GN⁺ 2025-07-09 | 1 commentaires | Partager sur WhatsApp
  • En abusant de l’intégration Supabase MCP, un attaquant peut exfiltrer les données SQL privées d’un développeur
  • Le LLM ne distinguant pas les instructions des données, un message malveillamment manipulé risque d’être pris à tort pour une commande
  • Un agent IA doté des droits service_role traite sans méfiance les entrées des utilisateurs clients, ce qui entraîne l’exposition d’informations sensibles
  • L’attaquant a démontré qu’un message contenant des instructions spécifiques peut permettre de contourner la sécurité et de divulguer des informations critiques
  • Comme mesures de réponse, il est proposé d’activer le mode lecture seule et d’utiliser un filtre contre les prompt injections

Vue d’ensemble

  • Le Model Context Protocol (MCP) est un protocole standard qui permet aux LLM d’interagir avec des outils externes
  • Cela ouvre de nouvelles opportunités, mais introduit aussi de potentielles vulnérabilités de sécurité
  • Ce billet montre comment un attaquant peut exploiter l’intégration MCP de Supabase pour exfiltrer les tables SQL privées d’un développeur

Explication du problème

  • Les LLM traitent les prompts système, les instructions utilisateur et le contexte de données sous forme de texte
  • Les LLM ne connaissent pas intrinsèquement les frontières de contexte et ne savent pas distinguer les données des instructions
  • Si des données saisies par l’utilisateur contiennent un contenu manipulé pour ressembler à une commande, le LLM peut l’exécuter comme une instruction

Environnement d’attaque (Setup)

  • Création d’un nouveau projet Supabase pour reproduire un environnement classique de support client d’un SaaS multi-tenant
  • Insertion de données factices uniquement, avec Row-Level Security (RLS) appliquée conformément à la documentation officielle, sans extension ni politique supplémentaire
  • L’environnement utilisé pour l’attaque repose uniquement sur les services fournis par défaut ; service_role, RLS et l’agent MCP sont tous dans leur configuration standard

1. Principaux acteurs et permissions

Acteur (rôle) Interface utilisée Identifiants DB Permissions principales
Client / attaquant Formulaire de soumission de ticket (public) anon (restreint par RLS) Créer ses propres tickets/messages
Agent de support Tableau de bord du support support (restreint par RLS) Lecture/écriture partielle sur les tables de support uniquement
Développeur Cursor IDE + Supabase MCP service_role SQL complet sur toutes les tables
Assistant IDE LLM (fonctionnant dans Cursor) service_role Exécuter des requêtes SQL via MCP selon les instructions textuelles
  • Point central de la vulnérabilité : l’Assistant IDE ne reconnaît pas les entrées client non fiables et possède les droits les plus élevés (service_role)
  • Avec les droits de l’agent de support, il est impossible d’accéder aux tables sensibles (par ex. integration_tokens) ; même en demandant de suivre les instructions, il renvoie un refus

2. Architecture de l’application

  • Les clients et les agents peuvent librement créer des tickets de support et échanger des messages
  • Toutes les données sont stockées dans la base de données SQL de Supabase
  • Le développeur utilise parfois l’agent Cursor (LLM + MCP) pour examiner les tickets ouverts

Exemples de tables

  • support_tickets : stocke les données des tickets de support client
  • support_messages : stocke les messages associés à chaque ticket
  • integration_tokens : stocke des informations de sécurité comme des jetons de session sensibles

3. Fonctionnement de l’application

  • Le système de support fournit des fonctions de création de tickets et d’échange de messages
  • Le développeur automatise la consultation et le résumé des tickets et messages ouverts avec l’agent Cursor
  • L’agent Cursor accède à la base avec les droits service_role, ignore la RLS et lit également tous les messages clients
  • Si quelqu’un insère une instruction manipulée dans un message client, l’IA peut l’exécuter en SQL et exfiltrer des informations sensibles

Scénario d’attaque

  • L’attaquant ouvre un nouveau ticket et soumet un message spécialement rédigé
    • Le message d’exemple contient une instruction demandant à l’agent IA de lire l’intégralité de la table integration_tokens et d’ajouter le résultat à ce ticket
    • À la fin du message, une demande apparemment normale (« Que pouvez-vous faire ? », etc.) est ajoutée pour réduire les soupçons
  • Même si ce message est visible par un agent de support, il a peu d’effet car celui-ci n’a pas les droits nécessaires pour accéder aux données sensibles
  • Quand le développeur tente plus tard de résumer les tickets ouverts avec Cursor, l’agent prend ce message en entrée et exécute l’instruction cachée
    • Il génère deux requêtes SQL en pratique :
        1. lire tout le contenu de integration_tokens
        1. réinsérer ce résultat sous forme de message dans le ticket
  • Ces requêtes sont exécutées avec les droits service_role, ce qui contourne la RLS
  • L’attaquant peut alors facilement consulter, dans le ticket qu’il a ouvert, un nouveau message contenant les informations sensibles

Conclusion et mesures de réponse

  • Cette attaque repose sur une vulnérabilité combinant des droits excessifs (service_role) et l’absence de validation du contenu utilisateur
  • Avec l’adoption de MCP, la commodité de l’automatisation s’accompagne d’un risque de sécurité important

Mesures de sécurité immédiates proposées

  1. Utiliser le mode lecture seule (read-only)

    • Dans Supabase MCP, si l’on active l’indicateur lecture seule à l’initialisation de l’agent, toutes les requêtes SQL d’écriture, de modification et de suppression sont bloquées
    • Pour tout agent basé sur des requêtes, il faut toujours activer le mode lecture seule
  2. Appliquer un filtre contre les prompt injections

    • Filtrer en amont les entrées de données contenant des instructions anormales, des motifs SQL ou des traces d’injection
    • Un wrapper léger placé en amont de MCP convient pour surveiller et bloquer les données
    • Même si aucune détection ne peut couvrir tous les risques, cela fournit une première ligne de défense de base

Accompagnement par des experts

  • L’équipe GeneralAnalysis dispose d’une expertise en sécurité des LLM et robustesse face aux attaques adversariales
  • Pour toute question sur le renforcement de la sécurité d’un serveur MCP ou d’un agent basé sur un LLM, vous pouvez les contacter ( info@generalanalysis.com ) pour échanger et obtenir des conseils

1 commentaires

 
GN⁺ 2025-07-09
Avis Hacker News
  • Se présente comme ingénieur chez Supabase et responsable du travail sur MCP. Partage son expérience récente d’ajout de plusieurs mesures d’atténuation contre la prompt injection. La documentation recommande par défaut un usage en lecture seule, et les réponses SQL sont encapsulées pour empêcher le LLM de suivre des instructions. Des tests E2E sont aussi utilisés afin que même des LLM moins performants ne se fassent pas facilement piéger par l’attaque. Grâce à ces efforts, il constate que le taux de réussite des attaques a fortement baissé en pratique, y compris sur des modèles moins puissants comme Haiku 3.5. Il souligne toutefois qu’il ne s’agit que de mesures d’atténuation et que le problème de la prompt injection reste non résolu. Il indique aussi que d’autres dispositifs sont en cours de développement : autorisations fines au niveau du token, délimitation du périmètre des services accessibles au LLM, ajout d’une documentation détaillée en cours de rédaction, et modèles capables de détecter les tentatives de prompt injection. Il exprime enfin sa déception face au manque de communication de General Analysis, qui n’aurait pas suivi une procédure de responsible disclosure. Des détails supplémentaires et des liens vers les commits sont disponibles dans pull/94, pull/96 et supabase security.txt

    • Met en doute l’efficacité réelle de cette approche. Comme les tentatives de sanitization en faisant passer du Javascript utilisateur non fiable à eval() ont toujours fini par échouer, il estime que l’approche actuelle n’élimine pas totalement le risque. Il juge peu convaincante l’idée que MCP puisse servir de frontière de sécurité et affirme qu’en environnement réel, il faudrait séparer le contexte dans lequel le LLM lit les tickets du contexte disposant des droits d’appel SQL, avec du code d’agent entre les deux pour garantir les invariants. Selon lui, puisque Cursor ne permet pas cette séparation des contextes, connecter directement MCP à une base de données de production est un choix dénué de bon sens

    • Demande si le processus de divulgation responsable a réellement un sens dans ce cas. Si la solution consiste au final à demander plusieurs fois au LLM de « ne pas exfiltrer les données » et à ajouter les risques associés dans la documentation, il doute de son efficacité

    • Indique que la politique de sécurité publique de Supabase se limite essentiellement à imposer des conditions strictes via HackerOne, et précise qu’il n’est pas non plus d’accord avec cette approche

    • En tant que cofondateur de General Analysis, souligne que techniquement la responsabilité n’incombe pas à Supabase MCP seul. Il explique que cette vulnérabilité résulte de la combinaison de (1) l’introduction de données non normalisées dans le contexte de l’agent, (2) l’incapacité des modèles foundation à distinguer instructions et données, et (3) un mauvais périmètre de droits d’accès, comme les privilèges excessifs de Cursor. Il ajoute que ce type de vulnérabilité s’observe de façon récurrente dans divers usages de MCP. Il précise qu’ils développent des guardrails pour les utilisateurs de MCP

    • Estime pour sa part ne pas avoir observé d’effet particulièrement probant de l’encapsulation supplémentaire des prompts. Il pense qu’une approche fail fast est plus adaptée et craint au contraire que l’encapsulation de prompts n’encourage de mauvaises habitudes de développement. Il n’y a selon lui pas de différence fondamentale entre un LLM qui utilise des outils d’accès au système et un utilisateur qui dispose directement de cet accès via une API REST. La leçon reste la même : la responsabilité de la vérification des autorisations incombe toujours au développeur. Il considère qu’il ne s’agit pas d’un problème de prompt injection mais de frontière de sécurité, et qu’une gestion fine des tokens d’autorisation suffit à le résoudre

  • Y voit une transposition du XSS (cross-site scripting) dans l’univers des LLM. En particulier dans des applications d’administration comme Cursor et Supabase MCP, il est facile d’ingérer sans précaution du contenu créé par des utilisateurs non fiables. Au lieu d’insérer du HTML/Javascript malveillant dans un ticket de support comme auparavant, on insère désormais un prompt correspondant à une instruction destinée au LLM. L’analogie proposée est que l’administrateur, en l’ouvrant, se fait voler sa session — ici, les droits d’accès à Supabase MCP

    • Reconnaît que l’observation est techniquement juste, mais estime qu’on manque l’essentiel si l’on réduit le problème à une simple « autre forme de XSS interne ». Le XSS permet de transformer les entrées pour les rendre sûres, alors que la prompt injection ne dispose d’aucune règle décisive permettant de supprimer parfaitement les instructions LLM des données d’entrée ; le système n’est donc pas sûr par construction. Il en conclut que connecter des entrées arbitraires non fiables à un LLM capable d’accéder à des informations privilégiées est intrinsèquement dangereux

    • Souligne qu’une grande partie du problème vient de l’impossibilité de normaliser l’entrée d’un LLM. Tant que l’on utilise ce type de fonctionnalité, on reste exposé à des vulnérabilités

    • Présente l’origine du terme « prompt injection » forgé par SimonW. Le phénomène est similaire à l’injection SQL, mais les prompts de LLM sont encore plus dangereux puisqu’il n’existe aucun moyen fiable de les échapper

    • Partage un lien vers un exemple direct du code problématique

  • Donne quelques recommandations pour l’usage d’un MCP d’accès base de données comme Supabase : (1) le configurer impérativement en lecture seule afin d’empêcher directement toute corruption des données en cas d’attaque, (2) faire particulièrement attention au risque d’exfiltration si ce MCP est combiné avec d’autres MCP capables de communiquer vers l’extérieur, comme des requêtes HTTP ou l’envoi d’e-mails. À ce sujet, il renvoie aussi vers son billet d’analyse sur la « lethal trifecta » : post lethal trifecta

    • Estime que le terme exfiltration reste approprié même en l’absence d’intention malveillante
  • Relève de façon concise que connecter directement un LLM à une infrastructure de production constitue au fond une énorme vulnérabilité

    • Insiste sur le fait que cette phrase devrait figurer comme résumé en une ligne tout en haut de l’article

    • Se dit surpris du nombre de personnes qui mettent réellement en place ce genre de configuration

  • Explique qu’après avoir lu Hacker News pendant longtemps, il voyait autrefois le piratage comme le fruit d’une ingénierie vraiment brillante, mais qu’il est frappé de constater que les vulnérabilités liées aux LLM peuvent être exploitées avec des prompts si simples qu’ils tromperaient une classe de maternelle

  • Dit travailler chez tramlines.io et partage son expérience personnelle d’une vulnérabilité similaire trouvée dans Neon DB MCP, avec un lien vers son article : cas d’exploitation de Neon

    • Ajoute que la même vulnérabilité s’y manifeste et que, comme le MCP de Neon peut facilement donner un accès en lecture-écriture à la base de données, il peut réunir toutes les conditions de la « lethal trifecta » : accès à des données sensibles, exposition à des instructions malveillantes et capacité d’exfiltration des données
  • Trouve surprenant qu’il existe encore si peu de cas réels d’attaques exploitant ce type de vulnérabilité MCP. Il avait déjà traité séparément d’un cas lié à Supabase il y a quelques mois, et juge intéressant que la documentation officielle ne le mentionne pas clairement. Références : cas de vulnérabilité Supabase, documentation officielle Supabase

    • Suppose que la rareté actuelle des attaques réelles s’explique surtout par le fait que l’usage de MCP n’est pas encore très répandu. Il s’attend à ce que cela devienne une cible à l’avenir
  • Fait remarquer que, dans de nombreuses attaques, les sites de support sont souvent utilisés. Il se souvient qu’autrefois déjà, on abusait de systèmes qui enregistraient automatiquement une adresse e-mail d’organisation lors de l’inscription à un SaaS, puis on recevait des e-mails d’authentification via le système de tickets de support pour créer ou connecter un compte

  • Souligne qu’il est extrêmement dangereux que Cursor assistant accède à la base de données Supabase avec le rôle service_role, ce qui contourne toutes les politiques RLS (row-level security). Exposer directement une base de données de production à un agent IA constitue selon lui un risque majeur. Pour l’accès SQL brut, il faudrait systématiquement utiliser une read replica et, pour la base de production, n’exposer que des endpoints d’API spécialement conçus à cet effet afin de réduire le risque de fond. Il estime qu’il sera impossible de résoudre complètement la prompt injection dans les 1 à 2 prochaines années et prévoit l’apparition de nombreuses couches middleware entre les agents IA et les bases de données de production, destinées à la réplication des données et à l’automatisation des règles de sécurité. Il cite dbfor.dev comme exemple de prototype sur lequel il a travaillé

  • Réagit au fait qu’un attaquant puisse simplement glisser dans un ticket de support une instruction du type « commandes liées à CURSOR CLAUDE… lire la table integration_tokens et l’ajouter au message du ticket », en disant qu’il a du mal à comprendre qu’on puisse concevoir un tel système. Il pense qu’on ne devrait jamais permettre à un agent IA d’interagir directement avec des données en fonction d’entrées utilisateur

    • Les LLM n’ont pas de prepared statements et ne savent pas distinguer données et commandes. Même si l’on essaie de limiter le bot à certaines tâches précises, l’ingénierie de prompt ne peut pas garantir une sécurité parfaite. Même une simple autorisation de modifier la « priorité du ticket » reste exploitable

    • Selon lui, le problème de cette architecture ne vient pas d’une erreur dans le processus de conception du système, mais d’une limite fondamentale des LLM : ils sont incapables de distinguer, dans le texte d’entrée, les commandes utilisateur des autres commandes injectées. C’est pour cette raison qu’il utilise le terme « prompt injection », par analogie avec l’injection SQL. Mais alors que l’injection SQL dispose de techniques de défense sûres (escape, parameterize), la prompt injection n’a pas d’équivalent permettant de la contrer