minimatch 7.4.7 → 7.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,6 +7,43 @@ This is the matching library used internally by npm.
7
7
  It works by converting glob expressions into JavaScript `RegExp`
8
8
  objects.
9
9
 
10
+ ## Important Security Consideration!
11
+
12
+ > [!WARNING]
13
+ > This library uses JavaScript regular expressions. Please read
14
+ > the following warning carefully, and be thoughtful about what
15
+ > you provide to this library in production systems.
16
+
17
+ _Any_ library in JavaScript that deals with matching string
18
+ patterns using regular expressions will be subject to
19
+ [ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
20
+ if the pattern is generated using untrusted input.
21
+
22
+ Efforts have been made to mitigate risk as much as is feasible in
23
+ such a library, providing maximum recursion depths and so forth,
24
+ but these measures can only ultimately protect against accidents,
25
+ not malice. A dedicated attacker can _always_ find patterns that
26
+ cannot be defended against by a bash-compatible glob pattern
27
+ matching system that uses JavaScript regular expressions.
28
+
29
+ To be extremely clear:
30
+
31
+ > [!WARNING]
32
+ > **If you create a system where you take user input, and use
33
+ > that input as the source of a Regular Expression pattern, in
34
+ > this or any extant glob matcher in JavaScript, you will be
35
+ > pwned.**
36
+
37
+ A future version of this library _may_ use a different matching
38
+ algorithm which does not exhibit backtracking problems. If and
39
+ when that happens, it will likely be a sweeping change, and those
40
+ improvements will **not** be backported to legacy versions.
41
+
42
+ In the near term, it is not reasonable to continue to play
43
+ whack-a-mole with security advisories, and so any future ReDoS
44
+ reports will be considered "working as intended", and resolved
45
+ entirely by this warning.
46
+
10
47
  ## Usage
11
48
 
12
49
  ```js
package/changelog.md ADDED
@@ -0,0 +1,98 @@
1
+ # change log
2
+
3
+ ## 7.4
4
+
5
+ - Add `escape()` method
6
+ - Add `unescape()` method
7
+ - Add `Minimatch.hasMagic()` method
8
+
9
+ ## 7.3
10
+
11
+ - Add support for posix character classes in a unicode-aware way.
12
+
13
+ ## 7.2
14
+
15
+ - Add `windowsNoMagicRoot` option
16
+
17
+ ## 7.1
18
+
19
+ - Add `optimizationLevel` configuration option, and revert the
20
+ default back to the 6.2 style minimal optimizations, making the
21
+ advanced transforms introduced in 7.0 opt-in. Also, process
22
+ provided file paths in the same way in optimizationLevel:2
23
+ mode, so _most_ things that matched with optimizationLevel 1 or
24
+ 0 _should_ match with level 2 as well. However, level 1 is the
25
+ default, out of an abundance of caution.
26
+
27
+ ## 7.0
28
+
29
+ - Preprocess patterns to simplify complicated patterns and reduce
30
+ out `..` pattern portions where possible. Note that this means
31
+ a pattern like `a/b/../*` will be equivalent to `a/*`, and will
32
+ _not_ match the string `a/b/../c`. If this causes problems, it
33
+ can be addressed in a patch release by resolving `..` portions
34
+ in the test string.
35
+
36
+ ## 6.2
37
+
38
+ - Add nocaseMagicOnly flag
39
+
40
+ ## 6.1
41
+
42
+ - Handle UNC paths on Windows
43
+
44
+ This adds some slightly modified behavior when a pattern or path starts
45
+ with `//` on Windows.
46
+
47
+ - In the case of `//?/<drive letter>:/...`, the `?` is treated as a
48
+ literal character, rather than a wildcard. That is, `//?/c:` will
49
+ _not_ match `//x/c:`.
50
+ - UNC patterns starting with `//?/<drive letter>:/` will match file paths
51
+ starting with `<drive letter>:` if the drive letters match
52
+ case-insensitively.
53
+ - File paths starting with `//?/<drive letter>:/` will match file
54
+ patterns starting with `<drive letter>:` if the drive letters match
55
+ case-insensitively.
56
+
57
+ - Add `{preserveMultipleSlashes:true}` option to suppress the
58
+ behavior where multiple consecutive `/` characters would be
59
+ effectively coerced into a single path portion separator.
60
+
61
+ ## 6.0
62
+
63
+ - hybrid module supporting both `require()` and `import`
64
+ - exported types
65
+
66
+ ## 5.1
67
+
68
+ - use windowsPathNoEscape/allowWindowsEscape opts
69
+ - make character classes more faithful to bash glob behavior
70
+ - fix handling of escapes
71
+ - treat invalid character classes as non-matching pattern
72
+ rather than escaped literals
73
+
74
+ ## 5.0
75
+
76
+ - brace-expansion: ignore only blocks that begins with $
77
+ - Expect exclusively forward slash as path sep, same as node-glob
78
+
79
+ ## 4.2
80
+
81
+ - makeRe: globstar should match zero+ path portions
82
+ - Fix bug with escaped '@' in patterns
83
+
84
+ ## 4.1
85
+
86
+ - treat `nocase:true` as always having magic
87
+ - expose GLOBSTAR marker
88
+
89
+ ## 4.0
90
+
91
+ - Update to modern JS syntax
92
+ - Add `allowWindowsEscape` option
93
+
94
+ ## 3.x
95
+
96
+ - Added basic redos protection
97
+ - Handle unfinished `!(` extglob patterns
98
+ - Add `partial: true` option
@@ -11,6 +11,7 @@ export interface MinimatchOptions {
11
11
  allowWindowsEscape?: boolean;
12
12
  partial?: boolean;
13
13
  dot?: boolean;
14
+ maxGlobstarRecursion?: number;
14
15
  nocase?: boolean;
15
16
  nocaseMagicOnly?: boolean;
16
17
  magicalBraces?: boolean;
@@ -68,6 +69,7 @@ export declare class Minimatch {
68
69
  platform: Platform;
69
70
  windowsNoMagicRoot: boolean;
70
71
  regexp: false | null | MMRegExp;
72
+ maxGlobstarRecursion: number;
71
73
  constructor(pattern: string, options?: MinimatchOptions);
72
74
  hasMagic(): boolean;
73
75
  debug(..._: any[]): void;
@@ -81,6 +83,9 @@ export declare class Minimatch {
81
83
  partsMatch(a: string[], b: string[], emptyGSMatch?: boolean): false | string[];
82
84
  parseNegate(): void;
83
85
  matchOne(file: string[], pattern: ParseReturn[], partial?: boolean): boolean;
86
+ _matchGlobstar(file: string[], pattern: ParseReturn[], partial: boolean, fileIndex: number, patternIndex: number): boolean;
87
+ _matchGlobStarBodySections(file: string[], bodySegments: [ParseReturn[], number][], fileIndex: number, bodyIndex: number, partial: boolean, globStarDepth: number, sawTail: boolean): boolean | null;
88
+ _matchOne(file: string[], pattern: ParseReturn[], partial: boolean, fileIndex: number, patternIndex: number): boolean;
84
89
  braceExpand(): string[];
85
90
  parse(pattern: string): ParseReturn | SubparseReturn;
86
91
  makeRe(): false | MMRegExp;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/dist/cjs/index.js CHANGED
@@ -222,6 +222,7 @@ class Minimatch {
222
222
  platform;
223
223
  windowsNoMagicRoot;
224
224
  regexp;
225
+ maxGlobstarRecursion;
225
226
  constructor(pattern, options = {}) {
226
227
  assertValidPattern(pattern);
227
228
  options = options || {};
@@ -246,6 +247,8 @@ class Minimatch {
246
247
  options.windowsNoMagicRoot !== undefined
247
248
  ? options.windowsNoMagicRoot
248
249
  : !!(this.isWindows && this.nocase);
250
+ this.maxGlobstarRecursion = options.maxGlobstarRecursion !== undefined
251
+ ? options.maxGlobstarRecursion : 200;
249
252
  this.globSet = [];
250
253
  this.globParts = [];
251
254
  this.set = [];
@@ -623,7 +626,6 @@ class Minimatch {
623
626
  // out of pattern, then that's fine, as long as all
624
627
  // the parts match.
625
628
  matchOne(file, pattern, partial = false) {
626
- const options = this.options;
627
629
  // a UNC pattern like //?/c:/* can match a path like c:/x
628
630
  // and vice versa
629
631
  if (this.isWindows) {
@@ -668,97 +670,155 @@ class Minimatch {
668
670
  }
669
671
  this.debug('matchOne', this, { file, pattern });
670
672
  this.debug('matchOne', file.length, pattern.length);
671
- for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
673
+ if (pattern.indexOf(exports.GLOBSTAR) !== -1) {
674
+ return this._matchGlobstar(file, pattern, partial, 0, 0);
675
+ }
676
+ return this._matchOne(file, pattern, partial, 0, 0);
677
+ }
678
+ _matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
679
+ // find first globstar from patternIndex
680
+ let firstgs = -1;
681
+ for (let i = patternIndex; i < pattern.length; i++) {
682
+ if (pattern[i] === exports.GLOBSTAR) {
683
+ firstgs = i;
684
+ break;
685
+ }
686
+ }
687
+ // find last globstar
688
+ let lastgs = -1;
689
+ for (let i = pattern.length - 1; i >= 0; i--) {
690
+ if (pattern[i] === exports.GLOBSTAR) {
691
+ lastgs = i;
692
+ break;
693
+ }
694
+ }
695
+ const head = pattern.slice(patternIndex, firstgs);
696
+ const body = partial ? pattern.slice(firstgs + 1) : pattern.slice(firstgs + 1, lastgs);
697
+ const tail = partial ? [] : pattern.slice(lastgs + 1);
698
+ // check the head
699
+ if (head.length) {
700
+ const fileHead = file.slice(fileIndex, fileIndex + head.length);
701
+ if (!this._matchOne(fileHead, head, partial, 0, 0)) {
702
+ return false;
703
+ }
704
+ fileIndex += head.length;
705
+ }
706
+ // check the tail
707
+ let fileTailMatch = 0;
708
+ if (tail.length) {
709
+ if (tail.length + fileIndex > file.length)
710
+ return false;
711
+ const tailStart = file.length - tail.length;
712
+ if (this._matchOne(file, tail, partial, tailStart, 0)) {
713
+ fileTailMatch = tail.length;
714
+ }
715
+ else {
716
+ // affordance for stuff like a/**/* matching a/b/
717
+ if (file[file.length - 1] !== '' ||
718
+ fileIndex + tail.length === file.length) {
719
+ return false;
720
+ }
721
+ if (!this._matchOne(file, tail, partial, tailStart - 1, 0)) {
722
+ return false;
723
+ }
724
+ fileTailMatch = tail.length + 1;
725
+ }
726
+ }
727
+ // if body is empty (single ** between head and tail)
728
+ if (!body.length) {
729
+ let sawSome = !!fileTailMatch;
730
+ for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
731
+ const f = String(file[i]);
732
+ sawSome = true;
733
+ if (f === '.' ||
734
+ f === '..' ||
735
+ (!this.options.dot && f.startsWith('.'))) {
736
+ return false;
737
+ }
738
+ }
739
+ return partial || sawSome;
740
+ }
741
+ // split body into segments at each GLOBSTAR
742
+ const bodySegments = [[[], 0]];
743
+ let currentBody = bodySegments[0];
744
+ let nonGsParts = 0;
745
+ const nonGsPartsSums = [0];
746
+ for (const b of body) {
747
+ if (b === exports.GLOBSTAR) {
748
+ nonGsPartsSums.push(nonGsParts);
749
+ currentBody = [[], 0];
750
+ bodySegments.push(currentBody);
751
+ }
752
+ else {
753
+ currentBody[0].push(b);
754
+ nonGsParts++;
755
+ }
756
+ }
757
+ let idx = bodySegments.length - 1;
758
+ const fileLength = file.length - fileTailMatch;
759
+ for (const b of bodySegments) {
760
+ b[1] = fileLength - (nonGsPartsSums[idx--] + b[0].length);
761
+ }
762
+ return !!this._matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
763
+ }
764
+ // return false for "nope, not matching"
765
+ // return null for "not matching, cannot keep trying"
766
+ _matchGlobStarBodySections(file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
767
+ const bs = bodySegments[bodyIndex];
768
+ if (!bs) {
769
+ // just make sure there are no bad dots
770
+ for (let i = fileIndex; i < file.length; i++) {
771
+ sawTail = true;
772
+ const f = file[i];
773
+ if (f === '.' ||
774
+ f === '..' ||
775
+ (!this.options.dot && f.startsWith('.'))) {
776
+ return false;
777
+ }
778
+ }
779
+ return sawTail;
780
+ }
781
+ const [body, after] = bs;
782
+ while (fileIndex <= after) {
783
+ const m = this._matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
784
+ // if limit exceeded, no match. intentional false negative,
785
+ // acceptable break in correctness for security.
786
+ if (m && globStarDepth < this.maxGlobstarRecursion) {
787
+ const sub = this._matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
788
+ if (sub !== false) {
789
+ return sub;
790
+ }
791
+ }
792
+ const f = file[fileIndex];
793
+ if (f === '.' ||
794
+ f === '..' ||
795
+ (!this.options.dot && f.startsWith('.'))) {
796
+ return false;
797
+ }
798
+ fileIndex++;
799
+ }
800
+ return partial || null;
801
+ }
802
+ _matchOne(file, pattern, partial, fileIndex, patternIndex) {
803
+ let fi;
804
+ let pi;
805
+ let fl;
806
+ let pl;
807
+ for (fi = fileIndex,
808
+ pi = patternIndex,
809
+ fl = file.length,
810
+ pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
672
811
  this.debug('matchOne loop');
673
- var p = pattern[pi];
674
- var f = file[fi];
812
+ const p = pattern[pi];
813
+ const f = file[fi];
675
814
  this.debug(pattern, p, f);
676
815
  // should be impossible.
677
816
  // some invalid regexp stuff in the set.
678
817
  /* c8 ignore start */
679
- if (p === false) {
818
+ if (p === false || p === exports.GLOBSTAR) {
680
819
  return false;
681
820
  }
682
821
  /* c8 ignore stop */
683
- if (p === exports.GLOBSTAR) {
684
- this.debug('GLOBSTAR', [pattern, p, f]);
685
- // "**"
686
- // a/**/b/**/c would match the following:
687
- // a/b/x/y/z/c
688
- // a/x/y/z/b/c
689
- // a/b/x/b/x/c
690
- // a/b/c
691
- // To do this, take the rest of the pattern after
692
- // the **, and see if it would match the file remainder.
693
- // If so, return success.
694
- // If not, the ** "swallows" a segment, and try again.
695
- // This is recursively awful.
696
- //
697
- // a/**/b/**/c matching a/b/x/y/z/c
698
- // - a matches a
699
- // - doublestar
700
- // - matchOne(b/x/y/z/c, b/**/c)
701
- // - b matches b
702
- // - doublestar
703
- // - matchOne(x/y/z/c, c) -> no
704
- // - matchOne(y/z/c, c) -> no
705
- // - matchOne(z/c, c) -> no
706
- // - matchOne(c, c) yes, hit
707
- var fr = fi;
708
- var pr = pi + 1;
709
- if (pr === pl) {
710
- this.debug('** at the end');
711
- // a ** at the end will just swallow the rest.
712
- // We have found a match.
713
- // however, it will not swallow /.x, unless
714
- // options.dot is set.
715
- // . and .. are *never* matched by **, for explosively
716
- // exponential reasons.
717
- for (; fi < fl; fi++) {
718
- if (file[fi] === '.' ||
719
- file[fi] === '..' ||
720
- (!options.dot && file[fi].charAt(0) === '.'))
721
- return false;
722
- }
723
- return true;
724
- }
725
- // ok, let's see if we can swallow whatever we can.
726
- while (fr < fl) {
727
- var swallowee = file[fr];
728
- this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
729
- // XXX remove this slice. Just pass the start index.
730
- if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
731
- this.debug('globstar found match!', fr, fl, swallowee);
732
- // found a match.
733
- return true;
734
- }
735
- else {
736
- // can't swallow "." or ".." ever.
737
- // can only swallow ".foo" when explicitly asked.
738
- if (swallowee === '.' ||
739
- swallowee === '..' ||
740
- (!options.dot && swallowee.charAt(0) === '.')) {
741
- this.debug('dot detected!', file, fr, pattern, pr);
742
- break;
743
- }
744
- // ** swallows a segment, and continue.
745
- this.debug('globstar swallow a segment, and continue');
746
- fr++;
747
- }
748
- }
749
- // no match was found.
750
- // However, in partial mode, we can't say this is necessarily over.
751
- /* c8 ignore start */
752
- if (partial) {
753
- // ran out of file
754
- this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
755
- if (fr === fl) {
756
- return true;
757
- }
758
- }
759
- /* c8 ignore stop */
760
- return false;
761
- }
762
822
  // something other than **
763
823
  // non-magic patterns just have to match exactly
764
824
  // patterns with magic have been turned into regexps.
@@ -774,16 +834,6 @@ class Minimatch {
774
834
  if (!hit)
775
835
  return false;
776
836
  }
777
- // Note: ending in / means that we'll get a final ""
778
- // at the end of the pattern. This can only match a
779
- // corresponding "" at the end of the file.
780
- // If the file ends in /, then it can only match a
781
- // a pattern that ends in /, unless the pattern just
782
- // doesn't have any more for it. But, a/b/ should *not*
783
- // match "a/b/*", even though "" matches against the
784
- // [^/]*? pattern, except in partial mode, where it might
785
- // simply not be reached yet.
786
- // However, a/b/ should still satisfy a/*
787
837
  // now either we fell off the end of the pattern, or we're done.
788
838
  if (fi === fl && pi === pl) {
789
839
  // ran out of pattern and filename at the same time.