
Analyse basée sur CodeQL de la vulnérabilité de prototype pollution CVE-2025-55182 dans React Server Components, avec un POC d'exploitation et des requêtes de détection statique pour le parcours non sécurisé de propriétés.
Construire et exécuter :
docker compose build
docker compose run --rm --entrypoint 'npm install' node
docker compose run --rm --entrypoint 'npm run build' node
docker compose up
POC (depuis https://github.com/msanft/CVE-2025-55182) :
node poc.js
Expérimentation avec unbundled :
yarn --immutable
node --conditions react-server app.js
Cloner facebook/react et créer unbundled :
yarn --immutable
yarn cross-env RELEASE_CHANNEL=experimental node ./scripts/rollup/build.js react-server-dom-webpack/ --type=NODE_DEV
cp ./build/node_modules/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js \
codeql/${version}/
Préparer CodeQL :
codeql database create db -l javascript -s codeql
cd queries && codeql pack install
codeql query run ./queries/PrototypeTraversal.ql -d db
Promise.resolve(userData)
await non-native-promise
await sur une méthode qui retourne (parfois) des données brutesIl a détecté l'utilisation corrigée dans getOutlinedModel (ajout de hasOwnProperty.call) et celle supprimée dans createModelResolver (maintenant fulfillReference).
Je ne sais pas pourquoi le premier et le second pointent vers le même emplacement, alors que celui extrait dans vuln.js ne le fait pas.
Dans codeql/tests.js il y a ces trois variantes :
var value = {};
for (let i = 0; i < path.length; i++) {
value = value[path[i]] // VarAccess
}
var value = {};
for (let i = 0; i < path.length; i++) {
let c = value[path[i]] // VarDecl
value = c
}
var value = {};
for (let i = 0; i < path.length; i++) {
let c
c = value[path[i]] // use VarRef
value = c
}
| filename | source | sink |
|---|
| ./19.2.0/react-server-dom-webpack-server.node.unbundled.development.js | parentObject[reference[key]] | parentObject[reference[key]] | Parcours de prototype non sécurisé : la variable 'parentObject' est mise à jour avec sa propre propriété à l'intérieur d'une boucle. |
| ./19.2.0/react-server-dom-webpack-server.node.unbundled.development.js | parentObject[reference[key]] | parentObject[reference[key]] | Parcours de prototype non sécurisé : la variable 'parentObject' est mise à jour avec sa propre propriété à l'intérieur d'une boucle. |
| ./19.2.0/react-server-dom-webpack-server.node.unbundled.development.js | value[path[i]] | value[path[i]] | Parcours de prototype non sécurisé : la variable 'value' est mise à jour avec sa propre propriété à l'intérieur d'une boucle. |
| ./tests.js | value[path[i]] | c | Parcours de prototype non sécurisé : la variable 'value' est mise à jour avec sa propre propriété à l'intérieur d'une boucle. |
| ./tests.js | value[path[i]] | c | Parcours de prototype non sécurisé : la variable 'value' est mise à jour avec sa propre propriété à l'intérieur d'une boucle. |
| ./tests.js | value[path[i]] | value[path[i]] | Parcours de prototype non sécurisé : la variable 'value' est mise à jour avec sa propre propriété à l'intérieur d'une boucle. |
| ./vuln.js | parentObject[reference[key]] | parentObject[reference[key]] | Parcours de prototype non sécurisé : la variable 'parentObject' est mise à jour avec sa propre propriété à l'intérieur d'une boucle. |
| ./vuln.js | value[path[i]] | value[path[i]] | Parcours de prototype non sécurisé : la variable 'value' est mise à jour avec sa propre propriété à l'intérieur d'une boucle. |