FlawOpen

flawopen.com/Pollution de prototypes/lodash.merge()

lodash.merge() : risque de pollution de prototypes ?

CWE-1321: Prototype PollutionGuide de référence
Short answer

Imaginez qu’une fusion profonde copie les étiquettes d’un classeur étranger dans les registres principaux de votre application. Dans d’anciennes versions, certains chemins Lodash pouvaient traiter des noms de propriétés spéciaux comme des instructions menant à l’état partagé des prototypes. Les correctifs bloquent les chemins connus, mais copier tous les champs d’une requête crée toujours un risque d’affectation massive. Validez les champs acceptés par l’application.

VULNÉRABLE — versions Lodash concernées
const _ = require("lodash");

const settings = {};
const input = request.body;

_.merge(settings, input);
_.set(settings, request.query.path, request.query.value);
CORRIGÉ — mettre à jour et construire une forme connue
const allowedLocales = new Set(["en", "fr"]);
const input = request.body;

const settings = {
  theme: input.theme === "dark" ? "dark" : "light",
  locale: allowedLocales.has(input.locale)
    ? input.locale
    : "en",
};

Comment se déroule le chemin de vulnérabilité

Dans une version concernée, un JSON non fiable ou un chemin contrôlé par l’appelant atteint une fonction Lodash vulnérable. Une fusion récursive ou une opération de chemin traite mal un composant spécial et modifie ou supprime une propriété d’un prototype intégré. Un autre code peut ensuite lire cette propriété héritée ; l’effet dépend de la propriété et du gadget accessible dans l’application. La pollution de prototypes ne prouve pas à elle seule une exécution de code à distance.

Les avis du paquet npm lodash ont des périmètres distincts : CVE-2018-16487 concernait defaultsDeep, merge et mergeWith avant 4.17.11 ; CVE-2019-10744 concernait defaultsDeep avant 4.17.12 ; CVE-2020-8203 concernait pick, set, setWith, update, updateWith et zipObjectDeep avant 4.17.19. CVE-2025-13465 touchait unset et omit jusqu’à 4.17.22, corrigé en 4.17.23. Puis CVE-2026-2950 a touché ces deux méthodes dans 4.17.23, corrigé en 4.18.0. La dernière version vérifiée pour ce guide est 4.18.1. Ces plages sont propres à chaque paquet : vérifiez séparément les avis pour lodash-es, les modules et les versions distribuées par le système.

Vérifier et corriger la dépendance

npm install lodash@^4.18.1 npm ls lodash npm audit npm explain lodash

Mettez à jour les copies directes et transitives, enregistrez le lockfile actualisé et inspectez les copies vendoriées ou intégrées aux bundles. Ne transmettez pas directement les données de requête à une fusion profonde ni aux API de chemin ; construisez un nouvel objet avec des champs validés et autorisés. L’exemple évite les clés et chemins choisis par l’attaquant. Au 2026-10-05, Lodash 4.18.1 est la dernière version ; consultez les avis pour tout correctif ultérieur.

Questions fréquentes

lodash.merge() est-il sûr dans la dernière version ?

Les avis consultés pour le paquet npm lodash indiquent les correctifs pertinents dans les versions ultérieures ; 4.18.1 est la dernière version vérifiée ici. Maintenez-la à jour, vérifiez chaque copie installée et évitez de fusionner tout le corps d’une requête, car cela peut provoquer une affectation massive.

La pollution de prototypes entraîne-t-elle toujours une exécution de code à distance ?

Non. Elle modifie ou supprime des propriétés héritées. L’impact dépend de ce que l’application lit ou appelle ensuite et de l’existence d’un gadget accessible. Décrivez l’effet établi sans présumer d’une RCE.

lodash-es et les paquets lodash.* ont-ils les mêmes plages de versions ?

Pas nécessairement. Les avis peuvent indiquer des versions concernées et corrigées différentes pour chaque paquet. Vérifiez le nom exact, le lockfile et l’avis au lieu d’appliquer partout la plage de lodash.

Références

À voir aussi Pollution de prototypes JavaScript : causes et correctifs Object.assign() et Prototype Pollution : que risque-t-on ? JSON.parse() provoque-t-il une pollution de prototype ? JSON.parse() est-il plus sûr que eval() ?