diff --git a/packages/glob/__tests__/internal-pattern.test.ts b/packages/glob/__tests__/internal-pattern.test.ts index 3690ecb3b3..2f101d9fba 100644 --- a/packages/glob/__tests__/internal-pattern.test.ts +++ b/packages/glob/__tests__/internal-pattern.test.ts @@ -303,7 +303,7 @@ describe('pattern', () => { expect(pattern.match(`${root}foo/bar/baz`)).toBeFalsy() pattern = new Pattern(`${root}foo/b[!]r/b*`) expect(pattern.searchPath).toBe(`${root}foo${path.sep}b!r`) - expect(pattern.match(`${root}foo/b!r/baz`)).toBeTruthy() + expect(pattern.match(`${root}foo/b!r/baz`)).toBeFalsy() pattern = new Pattern(`${root}foo/b[[]ar/b*`) expect(pattern.searchPath).toBe(`${root}foo${path.sep}b[ar`) expect(pattern.match(`${root}foo/b[ar/baz`)).toBeTruthy() @@ -340,9 +340,18 @@ describe('pattern', () => { pattern = new Pattern('C:/foo/b\\[a]r/b*') expect(pattern.searchPath).toBe(`C:\\foo\\b\\ar`) expect(pattern.match('C:/foo/b/ar/baz')).toBeTruthy() + + // Regression testing for minimatch v3 + // Historically, minimatch/glob had a bug when parsing a character class + // containing an escaped '!' (e.g. `[\\!]`). In some cases, the internal + // pattern construction would incorrectly insert the literal string + // "undefined" into the generated pattern/segment, which could make a + // pattern intended to match `b[\\!]r` also match a path segment like + // `b[undefined/!]r`. This test ensures that a pattern with a literal + // `[\\!]` in the directory name does *not* match such malformed paths. pattern = new Pattern('C:/foo/b[\\!]r/b*') expect(pattern.searchPath).toBe('C:\\foo\\b[\\!]r') - expect(pattern.match('C:/foo/b[undefined/!]r/baz')).toBeTruthy() // Note, "undefined" substr to accommodate a bug in Minimatch when nocase=true + expect(pattern.match('C:/foo/b[undefined/!]r/baz')).toBeFalsy() } }) }) diff --git a/packages/glob/package-lock.json b/packages/glob/package-lock.json index 35920049b2..50cbc17cab 100644 --- a/packages/glob/package-lock.json +++ b/packages/glob/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "@actions/core": "^3.0.0", - "minimatch": "^3.0.4" + "minimatch": "^10.2.4" } }, "node_modules/@actions/core": { @@ -49,37 +49,39 @@ "license": "MIT" }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "*" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/tunnel": { diff --git a/packages/glob/package.json b/packages/glob/package.json index 81b58f8f46..b40834b7a6 100644 --- a/packages/glob/package.json +++ b/packages/glob/package.json @@ -45,6 +45,6 @@ }, "dependencies": { "@actions/core": "^3.0.0", - "minimatch": "^3.0.4" + "minimatch": "^10.2.4" } } diff --git a/packages/glob/src/internal-pattern.ts b/packages/glob/src/internal-pattern.ts index 61ee380473..f6fb740b4d 100644 --- a/packages/glob/src/internal-pattern.ts +++ b/packages/glob/src/internal-pattern.ts @@ -2,14 +2,10 @@ import * as os from 'os' import * as path from 'path' import * as pathHelper from './internal-path-helper.js' import assert from 'assert' -import minimatch from 'minimatch' +import {Minimatch, type MinimatchOptions} from 'minimatch' import {MatchKind} from './internal-match-kind.js' import {Path} from './internal-path.js' -type IMinimatch = minimatch.IMinimatch -type IMinimatchOptions = minimatch.IOptions -const {Minimatch} = minimatch - const IS_WINDOWS = process.platform === 'win32' export class Pattern { @@ -38,7 +34,7 @@ export class Pattern { /** * The Minimatch object used for matching */ - private readonly minimatch: IMinimatch + private readonly minimatch: Minimatch /** * Used to workaround a limitation with Minimatch when determining a partial @@ -126,7 +122,7 @@ export class Pattern { this.isImplicitPattern = isImplicitPattern // Create minimatch - const minimatchOptions: IMinimatchOptions = { + const minimatchOptions: MinimatchOptions = { dot: true, nobrace: true, nocase: IS_WINDOWS,