
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).
| 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. |
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
}