- Lot 1 (S8786, ReDoS) : 5 sites documentes NOSONAR apres preuve empirique (script reproductible docs/redos_probe_s8786.js), aucune reecriture defensive necessaire. - Lot 2 (S2703, variable globale implicite) : bug reel trouve et corrige (SCENE_OBJECT_NAMES en const au lieu de let, cassait la reassignation cross-script depuis scene-editor.js) + test de non-regression ; 4 autres sites confirmes surs et documentes. - Lot 3 (S2486, exceptions avalees) : 6 sites confirmes surs et documentes ; 2 sites (config sprite JSON invalide) corriges avec un console.warn devtools, comportement joueur inchange, couverts par un nouveau test. - Retrait du job CI sonarqube (.gitea/workflows/deploy.yml) et du service prod sonarqube/sonar-postgres (docker-compose.prod.yml) : acces dashboard bloque par des soucis d'infrastructure reseau (WSL2/pare-feu Hyper-V en local, reseau Docker partage avec Caddy pas en place en prod), sans lien avec le code du moteur - mis de cote plutot que de continuer a bloquer sur de l'infra. Les lots 4+ de modernisation JS dependent de scores Sonar exacts et sont donc egalement en pause (voir CODE_QUALITY.md). SKIP=djlint : H021 (styles inline, 49 occurrences) est un backlog deja documente et assume (CODE_QUALITY.md section 6), sur des templates non touches par ce commit - deja exclu de la CI pour la meme raison. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
58 lines
2.6 KiB
JavaScript
58 lines
2.6 KiB
JavaScript
// Script de verification empirique pour les 5 sites NOSONAR javascript:S8786
|
|
// (voir CODE_QUALITY.md, section 5) - teste les 3 regex distinctes flaguees
|
|
// (2 sont dupliquees dans 2 fichiers chacune) contre des entrees construites
|
|
// pour maximiser l'ambiguite que l'analyseur Sonar soupconne, a plusieurs
|
|
// tailles croissantes. Un vrai ReDoS montrerait une croissance exponentielle
|
|
// du temps avec la taille (x10 la taille -> beaucoup plus que x10 le temps).
|
|
//
|
|
// A relancer si l'une de ces 3 regex change de forme, pour confirmer que le
|
|
// NOSONAR reste justifie plutot que de le recopier aveuglement.
|
|
//
|
|
// Usage : node docs/redos_probe_s8786.js
|
|
|
|
function timeIt(label, fn) {
|
|
const start = process.hrtime.bigint();
|
|
const result = fn();
|
|
const end = process.hrtime.bigint();
|
|
const ms = Number(end - start) / 1e6;
|
|
console.log(`${label}: ${ms.toFixed(2)}ms -> match=${result !== null}`);
|
|
return ms;
|
|
}
|
|
|
|
console.log('=== Pattern A (filter-repeater-rows.js:10, panel-init.js:254) ===');
|
|
const patternA = /^\{\{\s*([^.{}]+)\.([^.{}]+)\s*\}\}$/;
|
|
for (const n of [1000, 10000, 50000, 100000]) {
|
|
const evil = `{{${'a'.repeat(n)}`; // pas de point, pas de fermeture
|
|
timeIt(` n=${n} (pas de point, pas de fermeture)`, () => patternA.exec(evil));
|
|
}
|
|
for (const n of [1000, 10000, 50000, 100000]) {
|
|
const evil = `{{${'a'.repeat(n)}.${'b'.repeat(n)}`; // point present, pas de fermeture
|
|
timeIt(` n=${n} (point present, pas de fermeture)`, () => patternA.exec(evil));
|
|
}
|
|
|
|
console.log('');
|
|
console.log('=== Pattern B (filter-repeater-rows.js:11, panel-init.js:261) ===');
|
|
const patternB = /^\{\{\s*\$([^.{}[\]]+)((?:\.[^.{}[\]]+|\[\d+\])*)\s*\}\}$/;
|
|
for (const n of [1000, 5000, 10000, 20000]) {
|
|
const evil = `{{$a${'.b'.repeat(n)}`; // repetition simple, pas de fermeture
|
|
timeIt(` n=${n} (${n} segments ".b", pas de fermeture)`, () => patternB.exec(evil));
|
|
}
|
|
for (const n of [1000, 5000, 10000, 20000]) {
|
|
const evil = `{{$a${'.b[0]'.repeat(n)}`; // alternance des deux branches
|
|
timeIt(` n=${n} (${n} segments ".b[0]" alternes, pas de fermeture)`, () => patternB.exec(evil));
|
|
}
|
|
|
|
console.log('');
|
|
console.log('=== Pattern C (xapi-client.js:132) ===');
|
|
const patternC = /\/+$/;
|
|
for (const n of [10000, 100000, 1000000]) {
|
|
const evil = '/'.repeat(n);
|
|
timeIt(` n=${n} (que des slashes)`, () => patternC.exec(evil));
|
|
}
|
|
|
|
console.log('');
|
|
console.log('=== Verification d\'equivalence (entrees valides normales, comportement inchange attendu) ===');
|
|
console.log('A sur "{{Objet.champ}}":', patternA.exec('{{Objet.champ}}'));
|
|
console.log('B sur "{{$var.champ[0].sous}}":', patternB.exec('{{$var.champ[0].sous}}'));
|
|
console.log('C sur "https://host///":', 'https://host///'.replace(patternC, ''));
|