
Problème avec AWS SAM CLI (CVE-2025-3047, CVE-2025-3048)
Ce README fournit une analyse détaillée de deux vulnérabilités de sécurité découvertes dans l'interface de ligne de commande AWS Serverless Application Model (AWS SAM CLI) – CVE-2025-3047 et CVE-2025-3048 – ainsi que les problèmes et correctifs au niveau du code. Les deux vulnérabilités impliquent une gestion inappropriée des liens symboliques (symlinks) pendant le processus de construction à l'aide de conteneurs Docker. Chaque section ci-dessous couvre une CVE avec un résumé, le code affecté (avec des références au code source de SAM CLI), le correctif et la manière dont il résout le problème, ainsi que des conseils de remédiation.
Ces défauts impliquent une gestion inappropriée des liens symboliques (symlinks) pendant le processus sam build --use-container. Les deux problèmes affectent les environnements de développement locaux (ils n'impactent pas les services ou ressources AWS déployés), mais pourraient permettre un accès non autorisé aux fichiers sur la machine hôte en abusant de la façon dont AWS SAM CLI traite les symlinks. Il est fortement recommandé de mettre à niveau AWS SAM CLI vers les versions corrigées (1.133.0+ pour CVE-2025-3047, et 1.134.0+ pour CVE-2025-3048).
GHSA-px37-jpqx-97q9 est une vulnérabilité de contournement de chemin dans AWS SAM CLI <= v1.132.0 qui permettait un accès non autorisé aux fichiers sur la machine hôte lors de sam build --use-container. Lors de la construction d'une application sans serveur à l'intérieur d'un conteneur Docker, SAM CLI suivait les liens symboliques dans le projet par défaut. Un attaquant capable de placer un lien symbolique malveillant dans le projet (pointant vers un fichier sensible de l'hôte) pouvait exploiter les privilèges élevés du conteneur Docker pour que ce fichier soit monté dans le conteneur et copié vers un emplacement accessible à l'intérieur du conteneur. En pratique, cela signifiait que des fichiers privilégiés de l'hôte (à l'extérieur du répertoire du projet) pouvaient être lus et exfiltrés via le conteneur de construction. Le problème a été corrigé dans v1.133.0. (Pour préserver la compatibilité ascendante dans les cas légitimes, SAM CLI v1.133.0 a introduit un drapeau d'adhésion --mount-symlinks pour réactiver l'ancien comportement si nécessaire.)
Cause racine et composant affecté : Le problème central réside dans la manière dont AWS SAM CLI monte les répertoires du projet et leurs liens symboliques dans le conteneur Docker utilisé pour les constructions. Dans le code d'AWS SAM CLI (module samcli.local.docker.container), avant le correctif, tous les liens symboliques de premier niveau dans le répertoire du projet étaient automatiquement résolus et montés par liaison (bind mount) dans le conteneur avec les mêmes privilèges élevés que le processus du conteneur. Le conteneur s'exécute en tant que root par défaut, donc résoudre et monter un lien symbolique pointant vers un chemin sensible de l'hôte donnait accès à ce fichier au conteneur, ce qu'un utilisateur non privilégié de l'hôte n'aurait normalement pas. Le code vulnérable ne restreignait pas suffisamment les liens symboliques à suivre/monter.
Plus précisément, dans la fonction qui crée les volumes Docker à monter pour la construction, SAM CLI traitait inconditionnellement les liens symboliques comme des fichiers/répertoires réels à monter. La vulnérabilité résidait dans la logique d'orchestration des conteneurs de SAM CLI, spécifiquement dans la méthode Container.create de samcli/local/docker/container.py. Dans les versions vulnérables, cette méthode tentait toujours de résoudre et de monter les cibles des liens symboliques du projet dans le conteneur Docker, indépendamment du contexte. Le code problématique est présenté ci-dessous, de SAM CLI v1.132.0 :
# samcli/local/docker/container.py (v1.132.0 - extrait vulnérable)
if self._host_dir:
mount_mode = "rw,delegated" if self._mount_with_write else "ro,delegated"
LOG.info("Montage de %s en %s:%s, dans le conteneur d'exécution", self._host_dir, self._working_dir, mount_mode)
_volumes = {
self._host_dir: {
"bind": self._working_dir,
"mode": mount_mode,
},
**self._create_mapped_symlink_files(), # Résout et monte toujours les symlinks (vulnérable)
}
Dans le code ci-dessus, _create_mapped_symlink_files() recherche les liens symboliques dans le répertoire du projet et les prépare pour le montage. Étant donné que cela était inclus inconditionnellement, tous les liens symboliques (y compris ceux pointant à l'extérieur du projet) étaient montés dans le conteneur. (voir aws/aws-sam-cli#7865)
Le défaut ici est que lors d'un sam build --use-container, SAM CLI traite les liens symboliques comme des fichiers à monter dans le conteneur. Si un lien symbolique pointait, par exemple, vers /etc/shadow sur l'hôte, le conteneur Docker (qui pourrait s'exécuter avec des privilèges élevés) montait ce fichier par liaison. C'est un classique contournement de chemin basé sur les liens symboliques, entraînant une escalade de privilèges – des fichiers de l'hôte auxquels l'utilisateur n'aurait normalement pas accès pouvaient être lus par le conteneur puis se retrouver dans la sortie de la construction.
Correctif (code corrigé dans v1.133.0) : Le correctif introduit une notion de contexte de construction et désactive la résolution des liens symboliques pendant les constructions conteneurisées. Dans la version corrigée, Container.create prend un paramètre supplémentaire indiquant le contexte (BUILD vs INVOKE), et ne résout les liens symboliques que si le contexte est l'invocation (lors de l'exécution locale de fonctions), pas pendant les constructions. Voici le code corrigé de la version patchée :
# samcli/local/docker/container.py (v1.133.0+ - extrait corrigé)
if self._host_dir:
mount_mode = "rw,delegated" if self._mount_with_write else "ro,delegated"
LOG.info("Montage de %s en %s:%s, dans le conteneur d'exécution", self._host_dir, self._working_dir, mount_mode)
mapped_symlinks = self._create_mapped_symlink_files() if self._resolve_symlinks(context) else {}
_volumes = {
self._host_dir: {
"bind": self._working_dir,
"mode": mount_mode,
},
**mapped_symlinks, # Ne monte les symlinks que si le contexte l'autorise explicitement (pas en construction)
}
Dans le code corrigé, _create_mapped_symlink_files() est encapsulé derrière une vérification de contexte. La nouvelle énumération ContainerContext définit des contextes comme BUILD et INVOKE, et _resolve_symlinks(context) renvoie False pour le contexte de construction. Ainsi, mapped_symlinks sera un dictionnaire vide pendant les constructions, ce qui signifie qu'aucun lien symbolique n'est monté dans le conteneur par défaut.