diff --git a/packages/glob/__tests__/internal-pattern.test.ts b/packages/glob/__tests__/internal-pattern.test.ts index 8a9ecc85cb..7ea4670be1 100644 --- a/packages/glob/__tests__/internal-pattern.test.ts +++ b/packages/glob/__tests__/internal-pattern.test.ts @@ -4,6 +4,7 @@ import * as path from 'path' import {MatchKind} from '../src/internal-match-kind' import {promises as fs} from 'fs' import {Pattern} from '../src/internal-pattern' +import { performance } from 'perf_hooks' const IS_WINDOWS = process.platform === 'win32' @@ -347,6 +348,17 @@ describe('pattern', () => { }) }) +describe('globEscape ReDos', () => { + it('done in 1s', () => { + const attackString = `${'['.repeat(100000)}\u0000` + const startTime = performance.now() + Pattern.globEscape(attackString) + const endTime = performance.now() + const timeTaken = endTime - startTime + expect(timeTaken).toBeLessThan(1000) + }) +}) + function getTestTemp(): string { return path.join(__dirname, '_temp', 'internal-pattern') } diff --git a/packages/glob/src/internal-pattern.ts b/packages/glob/src/internal-pattern.ts index e1dbbda843..be5ac48acc 100644 --- a/packages/glob/src/internal-pattern.ts +++ b/packages/glob/src/internal-pattern.ts @@ -188,7 +188,7 @@ export class Pattern { */ static globEscape(s: string): string { return (IS_WINDOWS ? s : s.replace(/\\/g, '\\\\')) // escape '\' on Linux/macOS - .replace(/(\[)(?=[^/]+\])/g, '[[]') // escape '[' when ']' follows within the path segment + .replace(/(\[)(?!\[{500})([^/]+\])/g, '[[]$2') // escape '[' when ']' follows within the path segment .replace(/\?/g, '[?]') // escape '?' .replace(/\*/g, '[*]') // escape '*' }