Transmission des journaux, des alertes et des données de télémétrie via une diode de données

Découvrez comment
Nous utilisons l'intelligence artificielle pour les traductions de sites et, bien que nous nous efforcions d'être précis, il se peut que les traductions ne soient pas toujours exactes à 100 %. Nous vous remercions de votre compréhension.

CVE-2026-25049 : Sandbox d'expression pouvant entraîner l'exécution de code à distance dans n8n

Par Loc Nguyen, chef de l'équipe de test de pénétration
Partager cet article

En février 2026, une faille critique permettant de contourner le bac à sable a été rendue publique dans n8n, la plateforme open source d'automatisation des flux de travail largement adoptée. Répertoriée sous le numéro CVE-2026-25049, cette faille permet aux utilisateurs authentifiés de contourner le bac à sable d'évaluation des expressions et d'exécuter des commandes système arbitraires sur le serveur hôte, ce qui leur confère une capacité d'exécution de code à distance totale, avec un score CVSS v3.1 de 9,9.

Dans le cadre du programme de boursesOPSWAT , nos boursiers ont mené une analyse technique approfondie de la vulnérabilité CVE-2026-25049, en examinant sa cause profonde, son mécanisme d'exploitation et son impact sur les organisations.

Cet article propose une analyse détaillée de cette faille de sécurité, depuis l'architecture de traitement des expressions de n8n et ses contrôles de sécurité à plusieurs niveaux jusqu'à la technique précise qui permet de contourner simultanément les cinq couches de défense.

CVE-2026-25049 est une vulnérabilité critique de type « échappement du bac à sable » dans n8n, classée sous le code CWE-913 : « Contrôle inadéquat des ressources de code gérées dynamiquement ». Cette faille affecte toutes les versions de n8n antérieures à la version 1.123.17, ainsi que les versions 2.0.0 à 2.5.1, et a été corrigée dans les versions 1.123.17 et 2.5.2. Elle permet aux utilisateurs authentifiés disposant de droits de création de flux de travail de créer des expressions JavaScript malveillantes qui contournent le bac à sable d'expressions de la plateforme, ce qui leur permet finalement d'exécuter des commandes arbitraires sur le serveur hôte.

Figure 1 : CVE-2026-25049 (source : NVD)

Cette vulnérabilité est particulièrement grave car n8n occupe généralement une position privilégiée au sein de l'infrastructure d'une organisation. En tant que plateforme d'automatisation des flux de travail, n8n dispose généralement d'un accès direct aux API internes, aux bases de données, aux référentiels d'identifiants et aux services tiers. Une instance n8n compromise n'expose pas seulement le serveur d'automatisation : elle offre un point d'accès à tous les systèmes connectés, amplifiant considérablement la portée de l'exploitation.

La vulnérabilité CVE-2026-25049 n'est pas une découverte isolée, mais un contournement du correctif apporté à la vulnérabilité CVE-2025-68613, une faille antérieure permettant de s'échapper du bac à sable dans l'évaluateur d'expressions de n8n. Malgré la mise en place de défenses multicouches après la vulnérabilité initiale, une faille fondamentale dans la manière dont le sanitizer traite les types de nœuds de l'arbre syntaxique abstrait (AST) JavaScript a permis à la classe d'attaque d'origine de refaire surface via un vecteur syntaxique différent. Ce schéma — où un correctif traite la technique d'exploitation spécifique plutôt que la faiblesse de conception sous-jacente — met en évidence le défi persistant que représente la sécurisation des environnements d'évaluation de code dynamique.

Cette faille de sécurité a été révélée le 4 février 2026, en même temps que dix autres avis de sécurité concernant n8n, et a fait l'objet d'analyses indépendantes menées par plusieurs équipes de recherche en sécurité.

À propos de n8n

n8n est une plateforme open source d'automatisation des flux de travail qui permet aux organisations de connecter des systèmes, d'automatiser des processus et de créer des intégrations entre des centaines de services. Grâce à son adoption généralisée et à plus de 1 300 intégrations disponibles, n8n est devenu l'un des outils les plus populaires de sa catégorie. Il est utilisé par les équipes de développement et les entreprises pour automatiser tous les aspects, des outils internes aux pipelines de données stratégiques.

Figure 2 : Exemple de flux de travail n8n.

La plateforme prend en charge à la fois les déploiements en auto-hébergement et dans le cloud, et propose un générateur visuel de workflows ainsi qu’une prise en charge directe de JavaScript pour la logique personnalisée. L’architecture de n8n est basée sur des nœuds : les workflows sont composés de nœuds interconnectés qui transmettent des données au format JSON entre les déclencheurs, les actions et les étapes de fonction. L'exécution peut se faire en mode manuel pour les tests ou en mode production pour le déploiement en direct. Cette architecture, combinée à la prise en charge native des expressions JavaScript et à l'accès aux API internes et aux magasins d'identifiants, fait de n8n un outil d'automatisation puissant, mais aussi une cible de choix en cas de vulnérabilités.

Contexte technique

Arbres syntaxiques abstraits

Un arbre syntaxique abstrait (AST) est une représentation hiérarchique du code source générée par un analyseur syntaxique. Au lieu de traiter le code comme une simple chaîne de caractères, un AST le décompose en nœuds structurés représentant ses éléments syntaxiques : déclarations de variables, expressions de fonction, expressions de membres, identifiants et littéraux.

Figure 3 : Phases de compilation.

Il est essentiel de bien comprendre les types de nœuds AST pour mener à bien cette analyse, car les contrôles de sécurité de n8n s’appliquent au niveau de l’AST. Les modules de nettoyage inspectent des types de nœuds spécifiques afin de détecter et de bloquer les schémas dangereux. La vulnérabilité exploite le fait qu’une même opération sémantique – l’accès à la propriété d’un objet – peut générer des types de nœuds AST totalement différents selon la syntaxe JavaScript utilisée.

Figure 4 : Quelques nœuds AST en JavaScript.

Par exemple, l'expression `obj.constructor ` génère un nœud `MemberExpression `, tandis que `const { constructor } = obj` génère une `VariableDeclaration ` contenant un `ObjectPattern` avec un nœud `Property`. Les deux extraient la même propriété, mais les structures de l'AST sont fondamentalement différentes — et les sanitizers de n8n n'inspectent que le premier modèle.

Évaluation des expressions et architecture de sécurité de n8n

L'architecture de n8n est organisée en cinq couches : Frontend, CLI, Core, Workflow et Nodes. La couche Workflow gère l'évaluation des expressions, qui est le composant concerné par cette vulnérabilité.

Figure 5 : Aperçu du flux n8n.

n8n permet aux utilisateurs d'intégrer des expressions JavaScript dans les paramètres des nœuds de workflow afin de manipuler les données de manière dynamique. Ces expressions sont évaluées côté serveur à l'aide d'une bibliothèque appelée Tournament, qui analyse les expressions pour les convertir en un arbre syntaxique abstrait (AST) avant leur exécution. Des hooks de validation sont directement intégrés au processus de création de Tournament, effectuant des vérifications pendant la construction de l'AST afin d'intercepter les schémas dangereux avant l'exécution du code.

Figure 6 : Création initiale d'un tournoi.

Comme ces expressions s'exécutent au sein du même processus Node.js que le serveur n8n, la plateforme met en œuvre cinq couches de sécurité distinctes conçues pour empêcher tout code non fiable de s'échapper du bac à sable.

Couche 1 - Remplacement du contexte global

Avant d'évaluer une expression, n8n crée un contexte d'exécution restreint en remplaçant les objets et fonctions globaux dangereux. Des propriétés telles que `document`, `window`, `globalThis`, `eval`, `setTimeout`, `setInterval` et `Function` sont remplacées par des objets vides, ce qui empêche tout accès direct à ces fonctionnalités.

Figure 7 : Lancer le contexte global.
Figure 8 : Remplacer toutes les fonctions dangereuses.

Cette approche présente une limite inhérente : si un attaquant parvient à s'échapper du contexte restreint et à accéder à l'objet de processus global réel, les propriétés écrasées perdent toute pertinence.

Couche 2 - Validation par expressions régulières

Avant que l'expression n'atteigne l'évaluateur, n8n effectue une vérification d'expression régulière sur la chaîne d'expression brute afin de bloquer l'accès à la propriété du constructeur — un vecteur courant permettant d'obtenir le constructeur Function et d'exécuter du code.

Figure 9 : Validation par expression régulière.

L'expression régulière /\.\s*constructor/gm détecte l'accès à .constructor via la notation par points. Cependant, cette vérification présente une limite fondamentale, car JavaScript propose plusieurs voies syntaxiques pour accéder à la même propriété, qui n'impliquent pas toutes la notation par points.

Couche 3 - AST Runtime Sanitizer – PrototypeSanitizer

La défense la plus sophistiquée intervient lors de la construction de l'AST. Le hook PrototypeSanitizer parcourt l'AST et inspecte les nœuds MemberExpression afin de déterminer si la propriété accédée figure sur une liste noire de propriétés d'objets non sécurisées, notamment constructor, __proto__, prototype, mainModule et binding.

Figure 10 : Prototype de désinfectant.

Le sanitizer traite trois cas : la notation par point (obj.prop), où il vérifie le nom de l'identificateur ; la notation statique entre crochets (obj['prop']), où il vérifie la valeur littérale de la chaîne ; et les expressions dynamiques, qui sont encapsulées dans une fonction de sanitizer d'exécution. Comme le montre la figure 10, seuls les nœuds MemberExpression sont inspectés ; les schémas de déstructuration ne sont pas parcourus.

Couche 4 - Fonction de vérification de l'AST en exécution ThisSanitizer

Ajouté sous forme de correctif direct pour la vulnérabilité CVE-2025-68613, le module FunctionThisSanitizer intercepte les expressions de fonction invoquées immédiatement (IIFE) et les réécrit afin de lier `this` à un objet vide. Cela empêche l'exploitation de la technique utilisée dans l'exploit d'origine, où l'expression (function(){ return this })() entraînait une fuite de l'objet global du processus via la référence `this` non liée.

Figure 11 : Fonction GlobalThisSanitizer

Il est important de noter que ce désinfecteur ne traite que les nœuds de type FunctionExpression. Il interrompt explicitement son exécution pour tout élément appelé qui n'est pas une FunctionExpression, y compris les fonctions fléchées.

Les propriétés dangereuses telles que `eval`, `Function` et `process.mainModule` sont supprimées ou remplacées dans le contexte d'exécution, ce qui empêche tout accès direct aux primitives d'exécution de code, même si les couches précédentes sont contournées.

Analyse de la vulnérabilité

Cause profonde

La cause profonde de la vulnérabilité CVE-2026-25049 réside dans une hypothèse commune aux cinq couches de sécurité : chacune d'entre elles partait du principe que l'accès aux propriétés se ferait soit via la notation par points (obj.constructor), soit via la notation entre crochets (obj['constructor']). Aucune ne tenait compte de la syntaxe de déstructuration de JavaScript.

La déstructuration JavaScript permet d'extraire des propriétés d'objets à l'aide d'une structure AST fondamentalement différente :

// Traditional access - produces MemberExpression node
obj.constructor; // Blocked by regex, AST sanitizer, and runtime checks

// Destructuring - produces ObjectPattern → Property node
const { constructor } = obj; // Not checked by any layer

Bien que ces deux modèles aboutissent au même résultat, ils génèrent des représentations AST totalement différentes. Le PrototypeSanitizer inspecte uniquement les nœuds MemberExpression, tandis que l'expression régulière ne correspond qu'aux modèles .constructor. Les affectations par déstructuration créent des nœuds de type VariableDeclaration → ObjectPattern → Property, qu'aucun des sanitizers ne parcourt.

À cela s'ajoute la manière dont n8n gère les fonctions fléchées. Le FunctionThisSanitizer n'intercepte que les nœuds FunctionExpression et les réécrit pour lier `this` à un contexte sécurisé. Les fonctions fléchées génèrent des nœuds AST de type ArrowFunctionExpression, que le sanitizer ne traite pas. Étant donné que les fonctions fléchées héritent de `this` de leur portée englobante (le `this` lexical), elles permettent d'accéder au contexte global non sécurisé.

Ces deux omissions combinées entraînent un contournement complet : la déstructuration extrait le constructeur Function sans déclencher aucune vérification d'accès aux propriétés, et les fonctions fléchées fournissent un contexte d'exécution que le FunctionThisSanitizer n'intercepte pas.

Exploitation

Cette faille exploite ces deux failles pour contourner simultanément toutes les couches de sécurité. Nos collègues ont retracé le chemin d'exploitation suivant :

Étape 1 - Définition d'une fonction fléchée. La charge utile commence par une fonction fléchée encapsulée dans une expression de fonction à exécution immédiate (IIFE) :

={{(() => {
// Fonction fléchée - contourne FunctionThisSanitizer
...
})()}}

La fonction `FunctionThisSanitizer` vérifie si l'objet appelé est une `FunctionExpression` ; comme il s'agit ici d'une `ArrowFunctionExpression`, le sanitizer se termine prématurément sans réécrire l'appel. La fonction fléchée s'exécute avec un accès complet au contexte global réel.

Étape 2 - Contournement de la déstructuration. À l'intérieur d'une fonction fléchée, la déstructuration extrait le constructeur `Function` d'une instance de fonction fléchée :

const { constructor } = () => {};

Comme il s'agit d'une affectation par déstructuration, l'AST contient un nœud ObjectPattern plutôt qu'un MemberExpression. La vérification par expression régulière ne détecte aucun motif .constructor, et le PrototypeSanitizer n'inspecte jamais le nom de la propriété. L'attaquant détient désormais une référence au constructeur Function.

Étape 3 - Exécution de code dynamique. Une fois le constructeur de fonction obtenu, l'attaquant crée et exécute du code arbitraire :

return constructor(
'return process.mainModule.require("child_process").execSync("whoami").toString()',
)();

La fonction construite dynamiquement s'exécute en dehors du contexte du bac à sable et dispose d'un accès complet à l'objet de processus Node.js, ce qui permet l'exécution de commandes système arbitraires sur l'hôte.

Figure 12 : Charge utile finale de l'attaque

Preuve de concept

Afin de démontrer l'impact concret de cette vulnérabilité, nos chercheurs ont reproduit l'exploit dans un environnement de laboratoire contrôlé. Le scénario d'attaque consiste à héberger une instance n8n vulnérable et à importer un workflow contenant la charge utile malveillante au sein d'un paramètre de nœud — en ciblant spécifiquement le nœud « Edit Fields », qui permet l'évaluation d'expressions.

Figure 13 : Un administrateur importe un flux de travail malveillant.

Une fois le workflow déclenché, la charge utile contourne les cinq couches de filtrage et exécute un shell inversé sur le serveur hôte, redonnant ainsi à l'attaquant la possibilité d'exécuter des commandes à volonté.

Figure 14 : Exécution de la charge utile via un déclencheur de workflow.

Escalade via un webhook vers une exploitation de commande à distance sans authentification

La gravité de cette vulnérabilité augmente considérablement lorsqu'elle est associée à la fonctionnalité de webhook de n8n. n8n permet aux workflows d'exposer des points de terminaison HTTP sous forme de webhooks avec des options d'authentification configurables, notamment les jetons « bearer », l'authentification de base et, surtout, l'absence totale d'authentification. Un attaquant disposant d'un accès à la création de workflows peut configurer un webhook public avec l'authentification « none », intégrer la charge utile RCE dans un nœud connecté et activer le workflow. À ce stade, toute requête HTTP adressée à l'URL du webhook — depuis n'importe où sur Internet — déclenche l'exécution de commandes arbitraires sur le serveur hôte.

Cette chaîne d'escalade transforme la vulnérabilité CVE-2026-25049, initialement interne et nécessitant une authentification, en un vecteur d'attaque pratiquement sans authentification, exposé à l'ensemble d'Internet.

Atténuation

L'équipe n8n a corrigé la vulnérabilité CVE-2026-25049 dans les versions 1.123.17 et 2.5.2 en mettant en place une vérification des types en exécution dans les fonctions de nettoyage et en étendant la couverture de l'AST afin de prendre en charge les schémas de déstructuration. Les organisations utilisant les versions concernées doivent procéder à une mise à jour sans délai.

Si une mise à niveau immédiate n'est pas possible, les administrateurs doivent limiter les autorisations de création et de modification des flux de travail aux seuls utilisateurs de confiance et déployer n8n dans un environnement sécurisé, avec des privilèges système et un accès réseau restreints.

Compte tenu de la gravité de cette faille et de la facilité avec laquelle elle peut être exploitée – en particulier lorsqu'elle est associée à des webhooks publics –, les organisations devraient également passer au crible leurs flux de travail existants à la recherche d'expressions suspectes, surveiller l'exécution de commandes système anormales provenant du processus n8n et vérifier les configurations des webhooks afin de détecter tout point de terminaison exposé sans authentification.

Mesures d'atténuation avec OPSWAT

En tirant parti OPSWAT , les entreprises peuvent rapidement identifier les composants n8n vulnérables au sein de leur infrastructure et prendre des mesures avant que des failles ne soient exploitées. OPSWAT , une technologie fondamentale de la plateforme MetaDefender®, fournit un inventaire complet de tous les composants logiciels, bibliothèques et dépendances utilisés dans l'environnement d'une entreprise.

Figure 15 : Détection de la vulnérabilité CVE-2026-25049 dans OPSWAT

Comme le montre la figure 15, MetaDefender a analysé le fichier package.json contenant la dépendance n8n et a automatiquement classé la vulnérabilité CVE-2026-25049 comme « critique », en indiquant la plage de versions concernées et les versions corrigées recommandées pour la résolution. Cela permet aux équipes de sécurité d'identifier rapidement cette vulnérabilité et de la hiérarchiser au sein de leur environnement de déploiement.

OPSWAT est disponible dans MetaDefender et MetaDefender Software Chain™, ce qui permet aux équipes de sécurité de :

  • Identifiez rapidement les composants vulnérables : repérez immédiatement les dépendances open source touchées par des failles de sécurité liées à la sortie du bac à sable et à l'exécution de code, afin de pouvoir les corriger ou les supprimer sans délai.
  • Assurer une gestion proactive des correctifs et des mises à jour - Surveiller en permanence les composants open source afin de détecter les paquets obsolètes ou non sécurisés, ce qui permet d'effectuer des mises à jour en temps opportun et de réduire les risques.
  • Assurer la conformité et le reporting - Respecter les exigences réglementaires, alors que les cadres réglementaires imposent de plus en plus la transparence dans les chaînes d'approvisionnement logicielles.

Références

Restez à jour avec OPSWAT!

Inscrivez-vous dès aujourd'hui pour recevoir les dernières mises à jour de l'entreprise, de l'entreprise, des histoires, des informations sur les événements, et plus encore.