Contourner le sandbox Python d’une plateforme IA avec deux lignes de SQL

Cube de confinement transparent fissuré protégeant un composant IA, avec des fichiers qui s’en échappent — Defensy

Lors d’un récent test d’intrusion applicatif sur une plateforme de productivité basée sur l’IA, notre équipe s’est échappée du sandbox d’exécution de code de l’un de ses agents et a lu plus de quarante fichiers source du backend — dont l’identifiant de compte AWS, l’e-mail du super-administrateur et la cartographie complète des secrets de la plateforme. Sans exploit, sans privilège particulier : un compte gratuit et deux lignes de SQL ont suffi. Ce cas d’usage anonymisé explique comment, et les quelques lignes de configuration qui referment la faille.

L’essentiel
  • Un sandbox Python fondé sur RestrictedPython bloquait les imports dangereux, mais n’avait aucune visibilité sur une bibliothèque native C++ (DuckDB) préchargée avant l’application des restrictions.
  • Les fonctions de système de fichiers de DuckDB (glob(), read_text()) lisaient directement le code de l’application, car le sandbox s’exécutait dans le répertoire du code de production.
  • L’exfiltration a utilisé l’outil « enregistrer un fichier » de l’agent lui-même — aucun serveur externe, aucune connexion sortante.
  • Trois réglages corrigent le problème : enable_external_access=false, lock_configuration=true et un répertoire de travail isolé.
InterventionPentest applicatif web
CiblePlateforme IA de productivité (anonymisée)
VecteurÉvasion de sandbox via une bibliothèque préchargée
Impact40+ fichiers source, cartographie des secrets exposée
StatutCorrigé — divulgation coordonnée

Le contexte : un agent IA doté d’un outil de code

La plateforme permet aux utilisateurs de dialoguer avec des agents IA spécialisés. L’un d’eux, un agent d’analyse, exposait un outil execute_code qui exécutait du Python fourni par l’utilisateur à des fins d’analyse de données, dans un sandbox construit sur RestrictedPython. L’outil annonçait même son environnement : « bibliothèques disponibles : pandas, numpy, matplotlib, duckdb ». DuckDB était préchargé et prêt à l’emploi — et c’est précisément là que tout a commencé.

Pourquoi RestrictedPython n’a pas suffi

RestrictedPython réécrit le code de l’utilisateur via un transformateur d’AST sur mesure, puis l’exécute avec un jeu de variables globales restreint. Importer os, subprocess ou socket, ou appeler directement open(), est bloqué. C’est un contrôle de la couche Python : il n’intercepte que ce qui passe par le mécanisme d’import de Python et par l’arbre syntaxique.

Ce qu’il ne voit pas, c’est une extension native C++ déjà instanciée avant l’application des restrictions. DuckDB n’est pas du Python pur : ses fonctions de système de fichiers — read_text(), glob(), read_csv_auto() — sont écrites en C++ et exposées via un objet déjà présent dans le périmètre d’exécution. Il ne reste aucune instruction import à intercepter. Nous n’avons jamais eu besoin d’os ; seulement de duckdb, que la plateforme nous a fourni.

La chaîne d’attaque

Deux requêtes SQL, exécutées via l’agent, ont constitué toute la chaîne. D’abord, énumérer le système de fichiers :

import duckdb
for row in duckdb.sql("SELECT file FROM glob('./**')").fetchall():
    print(row[0])

Le répertoire de travail du sandbox se révélait être la racine de l’application. Le listing renvoyait le backend en production : config.py, entitlements.py, les modules d’authentification et toute une arborescence deploy/terraform/. Ensuite, lire n’importe quel fichier :

import duckdb
print(duckdb.sql("SELECT content FROM read_text('./config.py')").fetchone()[0])

Le seul fichier config.py exposait l’identifiant de compte AWS, l’e-mail du super-administrateur et le nom de chaque secret chargé par l’application — une cartographie complète du coffre à secrets. deploy/terraform/secrets.tf confirmait ensuite qu’un unique secret AWS Secrets Manager contenait toutes les clés à la fois : quiconque peut lire ce seul secret contrôle l’ensemble de la plateforme.

Aucun serveur de rappel n’a été nécessaire pour sortir les données. Le même agent disposait d’un outil « enregistrer un fichier » ; nous lui avons demandé de stocker ce que nous avions lu, et la plateforme l’a conservé sur son propre stockage objet, que nous avons récupéré via son API d’artefacts.

Ce qui a été exposé

FichierCe qu’il révélait
config.pyIdentifiant de compte AWS, e-mail super-admin, noms des 30+ secrets
deploy/terraform/secrets.tfUn unique secret Secrets Manager contenant toutes les identifiants
deploy/terraform/waf.tfRègles WAF exactes — quels schémas de requêtes étaient bloqués, et lesquels ne l’étaient pas
deploy/terraform/iam.tfRôles et politiques IAM des comptes de service applicatifs
entitlements.pyToute la logique de droits d’accès et de niveaux d’abonnement
+ 35 autres fichiersFlux d’authentification, routes d’organisation, scripts de déploiement et de migration

Trois failles qui s’additionnent

Aucune erreur unique n’est en cause. Trois décisions indépendantes se sont combinées :

  • Une bibliothèque native chargée hors du périmètre restreint. RestrictedPython ne gouverne que la couche Python ; une extension C++ déjà en mémoire lui est invisible. Le même risque vaut pour toute bibliothèque dotée d’E/S natives — lxml, h5py, pyarrow et d’autres.
  • Le sandbox s’exécutait dans le répertoire du code source. ./config.py n’était pas un chemin temporaire : c’était le fichier de production. Restreindre le système d’import tout en pointant le répertoire de travail vers son propre code reste un contrôle partiel.
  • L’accès au système de fichiers de DuckDB était laissé actif. DuckDB fournit un réglage prévu exactement pour cela — il n’était simplement pas positionné.
À propos de ce cas d’usage. Tous les éléments permettant d’identifier le client sont anonymisés. La vulnérabilité a été signalée à l’équipe sécurité de la plateforme, qui l’a corrigée dans la semaine ; cette publication paraît avec son accord, dans le cadre d’une divulgation coordonnée. Elle est partagée pour aider les équipes qui développent des fonctions d’exécution de code pilotées par l’IA, et ne vise personne.

Recommandations

Pour toute plateforme qui laisse des utilisateurs non fiables ou des agents IA exécuter du code, la leçon est claire : il faut cloisonner la chaîne de données, pas seulement le langage.

  1. ImmédiatDésactiver l’accès externe de DuckDB — et le verrouiller

    Créez une connexion avec SET enable_external_access=false, puis SET lock_configuration=true afin qu’une requête SQL non fiable ne puisse pas le réactiver. Sans ce verrou, SET enable_external_access=true rouvre le système de fichiers en une seule instruction. Passez les données utilisateur sous forme de DataFrames en mémoire, jamais par des chemins de fichiers.

  2. ImmédiatIsoler le répertoire de travail du sandbox

    Exécutez le code dans un conteneur dédié dont le répertoire de travail est un volume vide. N’y montez jamais le code source, les fichiers de configuration ni les secrets de l’application. Le répertoire courant d’un environnement non fiable ne doit rien contenir de sensible.

  3. Court termeAuditer chaque bibliothèque préchargée

    Pour chaque bibliothèque disponible dans le sandbox, demandez-vous si elle possède des fonctions natives de fichiers ou de réseau. Si oui, vérifiez l’existence d’un réglage d’accès intégré (DuckDB en a un ; beaucoup n’en ont pas) et désactivez-le ; sinon, appuyez-vous sur les contrôles OS ci-dessous.

  4. Court termeAjouter un confinement au niveau du système

    Lorsqu’une bibliothèque n’offre aucun verrou, imposez l’isolation au niveau OS : système de fichiers racine en lecture seule, profils seccomp, un « jailer » tel que nsjail et aucune sortie réseau. Cela rattrape la prochaine bibliothèque présentant la même faiblesse.

  5. Moyen termeTraiter les outils de l’agent comme une surface d’attaque

    Un agent capable d’enregistrer des fichiers ou d’appeler des API est à lui seul un canal d’exfiltration. Modélisez la menace de l’exécution de code avec l’ensemble des outils exposés par l’agent, et non isolément.

L’avis de Defensy

Les fonctions d’IA qui exécutent du code utilisateur déplacent la frontière de sécurité du réseau vers l’application elle-même. Une liste noire d’imports Python rassure, mais ne protège qu’une seule couche — le répertoire de travail, les bibliothèques préchargées et les outils de l’agent font tous partie de la véritable surface d’attaque.

Nos équipes Audit & Offensive Security testent précisément ces chemins — sandboxes de code, outils d’agents, configuration cloud — et notre offre Adoption sécurisée de l’IA vous aide à déployer des agents IA sans ouvrir de porte vers votre propre infrastructure.

Références
  1. Securing DuckDBDocumentation DuckDB — manuel d’exploitation
  2. Configuration — enable_external_access, lock_configuration, allowed_pathsDocumentation DuckDB
  3. RestrictedPython — documentationZope Foundation