From 03fa08147d1f8370f28ab80ea4251596374b9698 Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Tue, 12 Aug 2025 15:25:01 +0800 Subject: [PATCH 1/4] Update run_prettify.js fix(prettify): replace regex parsing to avoid ReDoS --- st/prettify/run_prettify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st/prettify/run_prettify.js b/st/prettify/run_prettify.js index 7c907b6dc..ef809657f 100644 --- a/st/prettify/run_prettify.js +++ b/st/prettify/run_prettify.js @@ -30,7 +30,7 @@ */ (function(){function aa(g){function r(){try{L.doScroll("left")}catch(ba){k.setTimeout(r,50);return}x("poll")}function x(r){if("readystatechange"!=r.type||"complete"==z.readyState)("load"==r.type?k:z)[B](n+r.type,x,!1),!l&&(l=!0)&&g.call(k,r.type||r)}var X=z.addEventListener,l=!1,E=!0,v=X?"addEventListener":"attachEvent",B=X?"removeEventListener":"detachEvent",n=X?"":"on";if("complete"==z.readyState)g.call(k,"lazy");else{if(z.createEventObject&&L.doScroll){try{E=!k.frameElement}catch(ba){}E&&r()}z[v](n+ "DOMContentLoaded",x,!1);z[v](n+"readystatechange",x,!1);k[v](n+"load",x,!1)}}function T(){U&&aa(function(){var g=M.length;ca(g?function(){for(var r=0;r=c?parseInt(e.substring(1),8):"u"===c||"x"===c?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e); return"\\"===e||"-"===e||"]"===e||"^"===e?"\\"+e:e}function c(e){var c=e.substring(1,e.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));e=[];var a="^"===c[0],b=["["];a&&b.push("^");for(var a=a?1:0,h=c.length;ap||122p||90p||122 Date: Tue, 12 Aug 2025 15:28:57 +0800 Subject: [PATCH 2/4] Add files via upload test --- tests/prettify-redos.test.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/prettify-redos.test.js diff --git a/tests/prettify-redos.test.js b/tests/prettify-redos.test.js new file mode 100644 index 000000000..4e6cbfea1 --- /dev/null +++ b/tests/prettify-redos.test.js @@ -0,0 +1,34 @@ +/** @jest-environment jsdom */ +'use strict'; +const path = require('path'); + +describe('run_prettify.js 第5段解析(真实文件)ReDoS 检测', () => { + const LENGTH = 100_000; + const THRESHOLD = 2000; + const MOD_PATH = path.join(__dirname, '..', 'st', 'prettify', 'run_prettify.js'); + + jest.setTimeout(THRESHOLD * 10); + + function runWithQuery(query) { + document.documentElement.innerHTML = ''; + const s = document.createElement('script'); + s.src = 'http://example.com/assets/run_prettify.js?' + query; + document.head.appendChild(s); + delete require.cache[require.resolve(MOD_PATH)]; + const t0 = Date.now(); + require(MOD_PATH); + return Date.now() - t0; + } + + test(`坏串("?".repeat(${LENGTH}) + "=") 必须 < ${THRESHOLD}ms`, () => { + const bad = '?'.repeat(LENGTH) + '='; + const dt = runWithQuery(bad); + console.log('[BAD] %dms', dt); + expect(dt).toBeLessThan(THRESHOLD); + }); +}); + + +//npx jest --version +//npm i -D jest-environment-jsdom@ +//npx jest tests/prettify-redos.test.js --runInBand From c77bfd7807b19baeae8d27f974d0dfcd40728354 Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Tue, 12 Aug 2025 17:16:12 +0800 Subject: [PATCH 3/4] Delete tests/prettify-redos.test.js --- tests/prettify-redos.test.js | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 tests/prettify-redos.test.js diff --git a/tests/prettify-redos.test.js b/tests/prettify-redos.test.js deleted file mode 100644 index 4e6cbfea1..000000000 --- a/tests/prettify-redos.test.js +++ /dev/null @@ -1,34 +0,0 @@ -/** @jest-environment jsdom */ -'use strict'; -const path = require('path'); - -describe('run_prettify.js 第5段解析(真实文件)ReDoS 检测', () => { - const LENGTH = 100_000; - const THRESHOLD = 2000; - const MOD_PATH = path.join(__dirname, '..', 'st', 'prettify', 'run_prettify.js'); - - jest.setTimeout(THRESHOLD * 10); - - function runWithQuery(query) { - document.documentElement.innerHTML = ''; - const s = document.createElement('script'); - s.src = 'http://example.com/assets/run_prettify.js?' + query; - document.head.appendChild(s); - delete require.cache[require.resolve(MOD_PATH)]; - const t0 = Date.now(); - require(MOD_PATH); - return Date.now() - t0; - } - - test(`坏串("?".repeat(${LENGTH}) + "=") 必须 < ${THRESHOLD}ms`, () => { - const bad = '?'.repeat(LENGTH) + '='; - const dt = runWithQuery(bad); - console.log('[BAD] %dms', dt); - expect(dt).toBeLessThan(THRESHOLD); - }); -}); - - -//npx jest --version -//npm i -D jest-environment-jsdom@ -//npx jest tests/prettify-redos.test.js --runInBand From c26fff9601b587d978e18e53e523417f90b4a1eb Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Thu, 14 Aug 2025 13:14:20 +0800 Subject: [PATCH 4/4] Add files via upload --- tests/prettify-redos.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/prettify-redos.test.js diff --git a/tests/prettify-redos.test.js b/tests/prettify-redos.test.js new file mode 100644 index 000000000..e4d3308b1 --- /dev/null +++ b/tests/prettify-redos.test.js @@ -0,0 +1,19 @@ +import { ClientFunction } from 'testcafe'; + +fixture`Prettify query parsing` + .page`http://localhost:8080/tests/prettify-runner.html`; + +const runWithAttack = ClientFunction(a => window.__runWithAttack(a)); +const getDuration = ClientFunction(() => window.__duration__); +const getStatus = ClientFunction(() => window.__status__); + +test('run_prettify.js completes within 2000ms', async t => { + const attack = '?'.repeat(10000) + '='; + await runWithAttack(attack); + await t.expect(getDuration()).ok({ timeout: 15000 }); + const status = await getStatus(); + const ms = await getDuration(); + await t.expect(ms).gt(0, `status=${status}`); + await t.expect(ms).lt(2000, `status=${status}`); +}); +