picomatch known bugs
npm6 known bugs in picomatch, with affected versions, fixes and workarounds. Sourced from upstream issue trackers.
6
bugs
Known bugs
| Severity | Affected | Fixed in | Title | Status | Source |
|---|---|---|---|---|---|
| high | 4.0.0 | 4.0.4 | Picomatch has a ReDoS vulnerability via extglob quantifiers ### Impact
`picomatch` is vulnerable to Regular Expression Denial of Service (ReDoS) when processing crafted extglob patterns. Certain patterns using extglob quantifiers such as `+()` and `*()`, especially when combined with overlapping alternatives or nested extglobs, are compiled into regular expressions that can exhibit catastrophic backtracking on non-matching input.
Examples of problematic patterns include `+(a|aa)`, `+(*|?)`, `+(+(a))`, `*(+(a))`, and `+(+(+(a)))`. In local reproduction, these patterns caused multi-second event-loop blocking with relatively short inputs. For example, `+(a|aa)` compiled to `^(?:(?=.)(?:a|aa)+)$` and took about 2 seconds to reject a 41-character non-matching input, while nested patterns such as `+(+(a))` and `*(+(a))` took around 29 seconds to reject a 33-character input on a modern M1 MacBook.
Applications are impacted when they allow untrusted users to supply glob patterns that are passed to `picomatch` for compilation or matching. In those cases, an attacker can cause excessive CPU consumption and block the Node.js event loop, resulting in a denial of service. Applications that only use trusted, developer-controlled glob patterns are much less likely to be exposed in a security-relevant way.
### Patches
This issue is fixed in picomatch 4.0.4, 3.0.2 and 2.3.2.
Users should upgrade to one of these versions or later, depending on their supported release line.
### Workarounds
If upgrading is not immediately possible, avoid passing untrusted glob patterns to `picomatch`.
Possible mitigations include:
- disable extglob support for untrusted patterns by using `noextglob: true`
- reject or sanitize patterns containing nested extglobs or extglob quantifiers such as `+()` and `*()`
- enforce strict allowlists for accepted pattern syntax
- run matching in an isolated worker or separate process with time and resource limits
- apply application-level request throttling and input validation for any endpoint that accepts glob patterns
### Resources
- Picomatch repository: https://github.com/micromatch/picomatch
- `lib/parse.js` and `lib/constants.js` are involved in generating the vulnerable regex forms
- Comparable ReDoS precedent: CVE-2024-4067 (`micromatch`)
- Comparable generated-regex precedent: CVE-2024-45296 (`path-to-regexp`) | fixed | osv:GHSA-c2c7-rcm5-vvqj |
| medium | any | \u2014 | Relative patterns and paths with dot in the base name The `isMatch` method always returns `true` for files starting with a period if a relative path is used. The `dot` option has no effect here.
```js
const picomatch = require('picomatch');
const isMatch = picomatch('../*.js');
const result = isMatch('../.test.js');
console.log(result); // true
```
Comparing behavior with micromatch:
```js
const picomatch = require('picomatch');
const micromatch = require('micromatch');
const pico = picomatch('../*.js');
const micro = micromatch.isMatch('../.test.js', '../*.js');
console.log(pico('../.test.js')); // true
console.log(micro); // false Will be `true` with { dot: true }
``` | fixed | github:2 |
| medium | any | \u2014 | Incorrect matching with curly braces and globstar #### Source
* mrmlnc/fast-glob#159
#### Actual behavior
The following filepathes is not matched by `minimatch`, `micromatch` and `picomatch` for the `{file.txt,directory/**/*}` pattern.
```
directory/.test.txt
directory/test.txt
```
But if you remove the `/*` part of the pattern, everything works correctly.
#### Expected behavior
Will be matched or documented :)
#### Code sample
Works fine:
```js
picomatch.makeRe('{file.txt,directory/**}', { dot: true });
```
* https://runkit.com/mrmlnc/5c6db74af4685d0012b8a037
Works bad:
```js
picomatch.makeRe('{file.txt,directory/**/*}', { dot: true });
```
* https://runkit.com/mrmlnc/5c6db7a2629c26001267cf8d | fixed | github:8 |
| medium | any | \u2014 | Brace expansion matches single item According to the braces library, braces expansion should not match a single item like `{foo}`. However, picomatch does interpret this expression.
braces:
```js
braces('{foo}')
//=> ['{foo}']
```
picomatch:
```js
picomatch.parse('{foo}').output
//=> '(foo)'
```
Compare that to when there are multiple items:
```js
braces('{foo,bar}')
//=> ['(foo|bar)']
picomatch.parse('{foo,bar}').output
//=> '(foo|bar)'
```
It seems to me like the behavior should match in both cases. | fixed | github:49 |
| medium | any | \u2014 | Glob **/!(*-dbg).@(js) is wrongly translated into RegExp and thus DOES match -dbg.js files The Glob:
```
**/!(*-dbg).@(js)
```
Which should match any `.js` files that do not end with `-dbg` is wrongly translated to:
```
^(?:(?:^|[\\/]|(?:(?:(?!(?:^|[\\/])\.{1,2}(?:[\\/]|$)).)*?)[\\/])(?:(?!(?:[^\\/]*?-dbg).@(js))[^\\/]*?)\.(js))$
```
Please note how for the negative backreference, the glob pattern `.@(js)` is literally taking into the regex and is not translated into a regexp / excapted itself? Expected RegExp would have been:
```
^(?:(?:^|[\\/]|(?:(?:(?!(?:^|[\\/])\.{1,2}(?:[\\/]|$)).)*?)[\\/])(?:(?!(?:[^\\/]*?-dbg)\.(js))[^\\/]*?)\.(js))$
``` | fixed | github:93 |
| medium | 4.0.0 | 4.0.4 | Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Matching ### Impact
picomatch is vulnerable to a **method injection vulnerability (CWE-1321)** affecting the `POSIX_REGEX_SOURCE` object. Because the object inherits from `Object.prototype`, specially crafted POSIX bracket expressions (e.g., `[[:constructor:]]`) can reference inherited method names. These methods are implicitly converted to strings and injected into the generated regular expression.
This leads to **incorrect glob matching behavior (integrity impact)**, where patterns may match unintended filenames. The issue does **not enable remote code execution**, but it can cause security-relevant logic errors in applications that rely on glob matching for filtering, validation, or access control.
All users of affected `picomatch` versions that process untrusted or user-controlled glob patterns are potentially impacted.
### Patches
This issue is fixed in picomatch 4.0.4, 3.0.2 and 2.3.2.
Users should upgrade to one of these versions or later, depending on their supported release line.
### Workarounds
If upgrading is not immediately possible, avoid passing untrusted glob patterns to picomatch.
Possible mitigations include:
- Sanitizing or rejecting untrusted glob patterns, especially those containing POSIX character classes like `[[:...:]]`.
- Avoiding the use of POSIX bracket expressions if user input is involved.
- Manually patching the library by modifying `POSIX_REGEX_SOURCE` to use a null prototype:
```js
const POSIX_REGEX_SOURCE = {
__proto__: null,
alnum: 'a-zA-Z0-9',
alpha: 'a-zA-Z',
// ... rest unchanged
};
### Resources
- fix for similar issue: https://github.com/micromatch/picomatch/pull/144
- picomatch repository https://github.com/micromatch/picomatch | fixed | osv:GHSA-3v7f-55p6-f55p |
API access
Get this data programmatically \u2014 free, no authentication.
curl https://depscope.dev/api/bugs/npm/picomatch