Packages / path-to-regexp / Security
path-to-regexp outputs backtracking regular expressions
Affected releases · path-to-regexp
- 7.x7.0.0 – 7.2.0No fix on this line yet
- 6.x6.0.0 – 6.2.2Fixed in 6.3.0
- 5.x to 4.x4.0.0 – 5.0.0No fix, no longer updated
- 3.x3.0.0 – 3.2.0Fixed in 3.3.0
- 2.x2.0.0 – 2.4.0No fix on this line yet
- 1.x1.0.0 – 1.8.0Fixed in 1.9.0
- 0.2.x0.2.0 – 0.2.5No fix on this line yet
- 0.1.x0.1.0 – 0.1.9Fixed in 0.1.10
- 0.0.x0.0.1 – 0.0.2No fix on this line yet
7.x has no fix yet; the newest fixed line:
npm install path-to-regexp@6.3.0Every release on a timeline
Not affected
9.0.0
1 release, latest
Affected
7.0.0 – 7.2.0
3 releases
Affected
6.0.0 – 6.2.2
5 releases
Fixed
6.3.0
1 release
Affected
5.0.0
1 release
Affected
4.0.0 – 4.0.5
6 releases
Affected
3.0.0 – 3.2.0
3 releases
Fixed
3.3.0
1 release
Affected
2.0.0 – 2.4.0
6 releases
Affected
1.0.0 – 1.8.0
17 releases
Fixed
1.9.0
1 release
Affected
0.0.1 – 0.1.9
12 releases
Fixed
0.1.10 – 0.1.13
4 releases
Affected
0.2.0 – 0.2.5
6 releases
What happens
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 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.
References