A bad regular expression is generated any time you have two parameters within a single segment, separated by something that is not a period (.). For example, /:a-:b.
Patches
For users of 0.1, upgrade to 0.1.10. All other users should upgrade to 8.0.0.
These versions add backtrack protection when a custom regex pattern is not provided:
They do not protect against vulnerable user supplied capture groups. Protecting against explicit user patterns is out of scope for old versions and not considered a vulnerability.
Version 7.1.0 can enable strict: true and get an error when the regular expression might be bad.
Version 8.0.0 removes the features that can cause a ReDoS.
Workarounds
All versions can be patched by providing a custom regular expression for parameters after the first in a single segment. As long as the custom regular expression does not match the text before the parameter, you will be safe. For example, change /:a-:b to /:a-:b([^-/]+).
If paths cannot be rewritten and versions cannot be upgraded, another alternative is to limit the URL length. For example, halving the attack string improves performance by 4x faster.
Details
Using /:a-:b will produce the regular expression /^\/([^\/]+?)-([^\/]+?)\/?$/. This can be exploited by a path such as /a${'-a'.repeat(8_000)}/a. OWASP has a good example of why this occurs, but the TL;DR is the /a at the end ensures this route would never match but due to naive backtracking it will still attempt every combination of the :a-:b on the repeated 8,000 -a.
Because JavaScript is single threaded and regex matching runs on the main thread, poor performance will block the event loop and can lead to a DoS. In local benchmarks, exploiting the unsafe regex will result in performance that is over 1000x worse than the safe regex. In a more realistic environment using Express v4 and 10 concurrent connections, this translated to average latency of ~600ms vs 1ms.
pillarjs/path-to-regexp (path-to-regexp)
### [`v1.9.0`](https://redirect.github.com/pillarjs/path-to-regexp/releases/tag/v1.9.0): Fix backtracking in 1.x
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.8.0...v1.9.0)
**Fixed**
- Add backtrack protection to 1.x release ([#320](https://redirect.github.com/pillarjs/path-to-regexp/issues/320)) [`925ac8e`](https://redirect.github.com/pillarjs/path-to-regexp/commit/925ac8e)
- Fix `re.exec(39;/test/route39;)` result ([#267](https://redirect.github.com/pillarjs/path-to-regexp/issues/267)) [`32a14b0`](https://redirect.github.com/pillarjs/path-to-regexp/commit/32a14b0)
### [`v1.8.0`](https://redirect.github.com/pillarjs/path-to-regexp/releases/tag/v1.8.0): Backport token to function options
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.7.0...v1.8.0)
**Added**
- Backport `TokensToFunctionOptions`
### [`v1.7.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#170--2016-11-08)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.6.0...v1.7.0)
- Allow a `delimiter` option to be passed in with `tokensToRegExp` which will be used for "non-ending" token match situations
### [`v1.6.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#160--2016-10-03)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.5.3...v1.6.0)
- Populate `RegExp.keys` when using the `tokensToRegExp` method (making it consistent with the main export)
- Allow a `delimiter` option to be passed in with `parse`
- Updated TypeScript definition with `Keys` and `Options` updated
### [`v1.5.3`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#153--2016-06-15)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.5.2...v1.5.3)
- Add `\\` to the ignore character group to avoid backtracking on mismatched parens
### [`v1.5.2`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#152--2016-06-15)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.5.1...v1.5.2)
- Escape `\\` in string segments of regexp
### [`v1.5.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#151--2016-06-08)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.5.0...v1.5.1)
- Add `index.d.ts` to NPM package
### [`v1.5.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#150--2016-05-20)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.4.0...v1.5.0)
- Handle partial token segments (better)
- Allow compile to handle asterisk token segments
### [`v1.4.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#140--2016-05-18)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.3.0...v1.4.0)
- Handle RegExp unions in path matching groups
### [`v1.3.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#130--2016-05-08)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.2.1...v1.3.0)
- Clarify README language and named parameter token support
- Support advanced Closure Compiler with type annotations
- Add pretty paths options to compiled function output
- Add TypeScript definition to project
- Improved prefix handling with non-complete segment parameters (E.g. `/:foo?-bar`)
### [`v1.2.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#121--2015-08-17)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.2.0...v1.2.1)
- Encode values before validation with path compilation function
- More examples of using compilation in README
### [`v1.2.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#120--2015-05-20)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.1.1...v1.2.0)
- Add support for matching an asterisk (`*`) as an unnamed match everything group (`(.*)`)
### [`v1.1.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#111--2015-05-11)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.1.0...v1.1.1)
- Expose methods for working with path tokens
### [`v1.1.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#110--2015-05-09)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.0.3...v1.1.0)
- Expose the parser implementation to consumers
- Implement a compiler function to generate valid strings
- Huge refactor of tests to be more DRY and cover new parse and compile functions
- Use chai in tests
- Add .editorconfig
### [`v1.0.3`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#103--2015-01-17)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.0.2...v1.0.3)
- Optimised function runtime
- Added `files` to `package.json`
### [`v1.0.2`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#102--2014-12-17)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.0.1...v1.0.2)
- Use `Array.isArray` shim
- Remove ES5 incompatible code
- Fixed repository path
- Added new readme badges
### [`v1.0.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#101--2014-08-27)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.0.0...v1.0.1)
- Ensure installation works correctly on 0.8
### [`v1.0.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#100--2014-08-17)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.5...v1.0.0)
- No more API changes
### [`v0.2.5`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#025--2014-08-07)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.4...v0.2.5)
- Allow keys parameter to be omitted
### [`v0.2.4`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#024--2014-08-02)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.3...v0.2.4)
- Code coverage badge
- Updated readme
- Attach keys to the generated regexp
### [`v0.2.3`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#023--2014-07-09)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.2...v0.2.3)
- Add MIT license
### [`v0.2.2`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#022--2014-07-06)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.1...v0.2.2)
- A passed in trailing slash in non-strict mode will become optional
- In non-end mode, the optional trailing slash will only match at the end
### [`v0.2.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#021--2014-06-11)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.0...v0.2.1)
- Fixed a major capturing group regexp regression
### [`v0.2.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#020--2014-06-09)
[Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.1.11...v0.2.0)
- Improved support for arrays
- Improved support for regexps
- Better support for non-ending strict mode matches with a trailing slash
- Travis CI support
- Block using regexp special characters in the path
- Removed support for the asterisk to match all
- New support for parameter suffixes - `*`, `+` and `?`
- Updated readme
- Provide delimiter information with keys array
Configuration
š Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).
š¦ Automerge: Disabled by config. Please merge this manually once you are satisfied.
ā» Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
š Ignore: Close this PR and you won't be reminded about this update again.
[ ] If you want to rebase/retry this PR, check this box
This PR contains the following updates:
^0.1.10
->^1.0.0
GitHub Vulnerability Alerts
CVE-2024-45296
Impact
A bad regular expression is generated any time you have two parameters within a single segment, separated by something that is not a period (
.
). For example,/:a-:b
.Patches
For users of 0.1, upgrade to
0.1.10
. All other users should upgrade to8.0.0
.These versions add backtrack protection when a custom regex pattern is not provided:
They do not protect against vulnerable user supplied capture groups. Protecting against explicit user patterns is out of scope for old versions and not considered a vulnerability.
Version 7.1.0 can enable
strict: true
and get an error when the regular expression might be bad.Version 8.0.0 removes the features that can cause a ReDoS.
Workarounds
All versions can be patched by providing a custom regular expression for parameters after the first in a single segment. As long as the custom regular expression does not match the text before the parameter, you will be safe. For example, change
/:a-:b
to/:a-:b([^-/]+)
.If paths cannot be rewritten and versions cannot be upgraded, another alternative is to limit the URL length. For example, halving the attack string improves performance by 4x faster.
Details
Using
/:a-:b
will produce the regular expression/^\/([^\/]+?)-([^\/]+?)\/?$/
. This can be exploited by a path such as/a${'-a'.repeat(8_000)}/a
. OWASP has a good example of why this occurs, but the TL;DR is the/a
at the end ensures this route would never match but due to naive backtracking it will still attempt every combination of the:a-:b
on the repeated 8,000-a
.Because JavaScript is single threaded and regex matching runs on the main thread, poor performance will block the event loop and can lead to a DoS. In local benchmarks, exploiting the unsafe regex will result in performance that is over 1000x worse than the safe regex. In a more realistic environment using Express v4 and 10 concurrent connections, this translated to average latency of ~600ms vs 1ms.
References
Release Notes
pillarjs/path-to-regexp (path-to-regexp)
### [`v1.9.0`](https://redirect.github.com/pillarjs/path-to-regexp/releases/tag/v1.9.0): Fix backtracking in 1.x [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.8.0...v1.9.0) **Fixed** - Add backtrack protection to 1.x release ([#320](https://redirect.github.com/pillarjs/path-to-regexp/issues/320)) [`925ac8e`](https://redirect.github.com/pillarjs/path-to-regexp/commit/925ac8e) - Fix `re.exec(39;/test/route39;)` result ([#267](https://redirect.github.com/pillarjs/path-to-regexp/issues/267)) [`32a14b0`](https://redirect.github.com/pillarjs/path-to-regexp/commit/32a14b0) ### [`v1.8.0`](https://redirect.github.com/pillarjs/path-to-regexp/releases/tag/v1.8.0): Backport token to function options [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.7.0...v1.8.0) **Added** - Backport `TokensToFunctionOptions` ### [`v1.7.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#170--2016-11-08) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.6.0...v1.7.0) - Allow a `delimiter` option to be passed in with `tokensToRegExp` which will be used for "non-ending" token match situations ### [`v1.6.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#160--2016-10-03) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.5.3...v1.6.0) - Populate `RegExp.keys` when using the `tokensToRegExp` method (making it consistent with the main export) - Allow a `delimiter` option to be passed in with `parse` - Updated TypeScript definition with `Keys` and `Options` updated ### [`v1.5.3`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#153--2016-06-15) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.5.2...v1.5.3) - Add `\\` to the ignore character group to avoid backtracking on mismatched parens ### [`v1.5.2`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#152--2016-06-15) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.5.1...v1.5.2) - Escape `\\` in string segments of regexp ### [`v1.5.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#151--2016-06-08) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.5.0...v1.5.1) - Add `index.d.ts` to NPM package ### [`v1.5.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#150--2016-05-20) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.4.0...v1.5.0) - Handle partial token segments (better) - Allow compile to handle asterisk token segments ### [`v1.4.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#140--2016-05-18) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.3.0...v1.4.0) - Handle RegExp unions in path matching groups ### [`v1.3.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#130--2016-05-08) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.2.1...v1.3.0) - Clarify README language and named parameter token support - Support advanced Closure Compiler with type annotations - Add pretty paths options to compiled function output - Add TypeScript definition to project - Improved prefix handling with non-complete segment parameters (E.g. `/:foo?-bar`) ### [`v1.2.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#121--2015-08-17) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.2.0...v1.2.1) - Encode values before validation with path compilation function - More examples of using compilation in README ### [`v1.2.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#120--2015-05-20) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.1.1...v1.2.0) - Add support for matching an asterisk (`*`) as an unnamed match everything group (`(.*)`) ### [`v1.1.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#111--2015-05-11) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.1.0...v1.1.1) - Expose methods for working with path tokens ### [`v1.1.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#110--2015-05-09) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.0.3...v1.1.0) - Expose the parser implementation to consumers - Implement a compiler function to generate valid strings - Huge refactor of tests to be more DRY and cover new parse and compile functions - Use chai in tests - Add .editorconfig ### [`v1.0.3`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#103--2015-01-17) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.0.2...v1.0.3) - Optimised function runtime - Added `files` to `package.json` ### [`v1.0.2`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#102--2014-12-17) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.0.1...v1.0.2) - Use `Array.isArray` shim - Remove ES5 incompatible code - Fixed repository path - Added new readme badges ### [`v1.0.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#101--2014-08-27) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v1.0.0...v1.0.1) - Ensure installation works correctly on 0.8 ### [`v1.0.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#100--2014-08-17) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.5...v1.0.0) - No more API changes ### [`v0.2.5`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#025--2014-08-07) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.4...v0.2.5) - Allow keys parameter to be omitted ### [`v0.2.4`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#024--2014-08-02) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.3...v0.2.4) - Code coverage badge - Updated readme - Attach keys to the generated regexp ### [`v0.2.3`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#023--2014-07-09) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.2...v0.2.3) - Add MIT license ### [`v0.2.2`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#022--2014-07-06) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.1...v0.2.2) - A passed in trailing slash in non-strict mode will become optional - In non-end mode, the optional trailing slash will only match at the end ### [`v0.2.1`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#021--2014-06-11) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.2.0...v0.2.1) - Fixed a major capturing group regexp regression ### [`v0.2.0`](https://redirect.github.com/pillarjs/path-to-regexp/blob/HEAD/History.md#020--2014-06-09) [Compare Source](https://redirect.github.com/pillarjs/path-to-regexp/compare/v0.1.11...v0.2.0) - Improved support for arrays - Improved support for regexps - Better support for non-ending strict mode matches with a trailing slash - Travis CI support - Block using regexp special characters in the path - Removed support for the asterisk to match all - New support for parameter suffixes - `*`, `+` and `?` - Updated readme - Provide delimiter information with keys arrayConfiguration
š Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).
š¦ Automerge: Disabled by config. Please merge this manually once you are satisfied.
ā» Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
š Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.