Mermaid Gantt Charts are vulnerable to an Infinite Loop DoS
Description
Impact
Mermaid v11.14.0 and earlier are vulnerable to a denial-of-service attack when rendering gantt charts, if they use the `excludes` attribute to exclude all dates.
Example:
gantt
excludes monday,tuesday,wednesday,thursday,friday,saturday,sunday
DoS :2025-01-01, 1d
mermaid.parse is unaffected, unless you then call the ganttDb.getTasks() (which is called when rendering a diagram).
Patches
This has been patched in:
- v11.15.0 (see faafb5d49106dd32c367f3882505f2dd625aa30e)
- v10.9.6 (see a59ea56174712ee5430dfd5bc877cb5151f501a6)
Workarounds
There are no workarounds available without updating to a newer version of mermaid.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Mermaid v11.14.0 and earlier vulnerable to denial-of-service via gantt charts when excludes removes all dates, causing an infinite loop.
Vulnerability
Mermaid [1] versions 11.14.0 and earlier contain a denial-of-service vulnerability in the Gantt chart rendering. The fixTaskDates function enters an infinite loop when the excludes attribute removes all weekdays (e.g., excludes monday,...,sunday), because no valid end date can be found [2][3].
Exploitation
An attacker can craft a Gantt diagram string with an excludes line covering all days and a task date range. When the diagram is rendered via ganttDb.getTasks(), the application hangs indefinitely, causing a denial-of-service condition. The diagram can be embedded in markdown or user input processed by Mermaid, requiring no special privileges.
Impact
Successful exploitation causes the application to become unresponsive, leading to a denial-of-service. This can affect services that render user-supplied Mermaid diagrams, such as documentation generators or live editors.
Mitigation
The vulnerability is patched in Mermaid versions 11.15.0 [2] and 10.9.6 [4]. Users should upgrade to these versions or later. No workarounds are available.
- GitHub - mermaid-js/mermaid: Generation of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown
- Release mermaid@11.15.0 · mermaid-js/mermaid
- fix(gantt): limit loop if excluding all dates · mermaid-js/mermaid@faafb5d
- fix(gantt): limit loop if excluding all dates · mermaid-js/mermaid@a59ea56
AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
mermaidnpm | >= 11.0.0-alpha.1, < 11.15.0 | 11.15.0 |
mermaidnpm | < 10.9.6 | 10.9.6 |
Affected products
2<= 10.9.5+ 1 more
- (no CPE)range: <= 10.9.5
- (no CPE)range: <= 11.14.0
Patches
2a59ea5617471fix(gantt): limit loop if excluding all dates
2 files changed · +22 −2
packages/mermaid/src/diagrams/gantt/ganttDb.js+9 −2 modified@@ -231,21 +231,28 @@ const checkTaskDates = function (task, dateFormat, excludes, includes) { * @param {dayjs.Dayjs} startTime - The start time. * @param {dayjs.Dayjs} endTime - The original end time (will return a different end time if it's invalid). * @param {string} dateFormat - Dayjs date format string. - * @param {*} excludes - * @param {*} includes + * @param {string[]} excludes - Dates or days to exclude. + * @param {string[]} includes - Dates to always include, even if they match the excludes. * @returns {[endTime: dayjs.Dayjs, renderEndTime: Date | null]} The new `endTime`, and the end time to render. * `renderEndTime` may be `null` if `startTime` is newer than `endTime`. + * @throws {Error} If a valid end time cannot be found after 10,000 iterations. */ const fixTaskDates = function (startTime, endTime, dateFormat, excludes, includes) { let invalid = false; let renderEndTime = null; + const maxEndTime = endTime.add(10000, 'd'); while (startTime <= endTime) { if (!invalid) { renderEndTime = endTime.toDate(); } invalid = isInvalidDate(startTime, dateFormat, excludes, includes); if (invalid) { endTime = endTime.add(1, 'd'); + if (endTime > maxEndTime) { + throw new Error( + 'Failed to find a valid date that was not excluded by `excludes` after 10,000 iterations.' + ); + } } startTime = startTime.add(1, 'd'); }
packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts+13 −0 modified@@ -267,6 +267,19 @@ describe('when using the ganttDb', function () { expect(tasks[6].task).toEqual('test7'); }); + it('should not infinite loop when excluding everything', function () { + ganttDb.setDateFormat('YYYY-MM-DD'); + ganttDb.setExcludes('weekends,monday,tuesday,wednesday,thursday,friday'); + ganttDb.addSection('weekends skip test'); + ganttDb.addTask('test1', 'id1,2019-02-01,7d'); + + expect(() => ganttDb.getTasks()).toThrowError('Failed to find a valid date'); + + // Fridays are now allowed, so it should not throw an error + ganttDb.setExcludes('weekends,monday,tuesday,wednesday,thursday'); + expect(() => ganttDb.getTasks()).not.toThrow(); + }); + it('should maintain the order in which tasks are created', function () { ganttDb.setAccTitle('Project Execution'); ganttDb.setDateFormat('YYYY-MM-DD');
faafb5d49106fix(gantt): limit loop if excluding all dates
3 files changed · +28 −2
.changeset/common-parents-serve.md+5 −0 added@@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix(gantt): add iteration limit for `excludes` field
packages/mermaid/src/diagrams/gantt/ganttDb.js+9 −2 modified@@ -245,21 +245,28 @@ const checkTaskDates = function (task, dateFormat, excludes, includes) { * @param {dayjs.Dayjs} startTime - The start time. * @param {dayjs.Dayjs} endTime - The original end time (will return a different end time if it's invalid). * @param {string} dateFormat - Dayjs date format string. - * @param {*} excludes - * @param {*} includes + * @param {string[]} excludes - Dates or days to exclude. + * @param {string[]} includes - Dates to always include, even if they match the excludes. * @returns {[endTime: dayjs.Dayjs, renderEndTime: Date | null]} The new `endTime`, and the end time to render. * `renderEndTime` may be `null` if `startTime` is newer than `endTime`. + * @throws {Error} If a valid end time cannot be found after 10,000 iterations. */ const fixTaskDates = function (startTime, endTime, dateFormat, excludes, includes) { let invalid = false; let renderEndTime = null; + const maxEndTime = endTime.add(10000, 'd'); while (startTime <= endTime) { if (!invalid) { renderEndTime = endTime.toDate(); } invalid = isInvalidDate(startTime, dateFormat, excludes, includes); if (invalid) { endTime = endTime.add(1, 'd'); + if (endTime > maxEndTime) { + throw new Error( + 'Failed to find a valid date that was not excluded by `excludes` after 10,000 iterations.' + ); + } } startTime = startTime.add(1, 'd'); }
packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts+14 −0 modified@@ -282,6 +282,20 @@ describe('when using the ganttDb', function () { expect(tasks[0].task).toEqual('test1'); }); + it('should not infinite loop when excluding everything', function () { + ganttDb.setDateFormat('YYYY-MM-DD'); + ganttDb.setExcludes('weekends,monday,tuesday,wednesday,thursday,friday'); + ganttDb.setWeekend('saturday'); + ganttDb.addSection('weekends skip test'); + ganttDb.addTask('test1', 'id1,2019-02-01,7d'); + + expect(() => ganttDb.getTasks()).toThrowError('Failed to find a valid date'); + + // Fridays are now allowed, so it should not throw an error + ganttDb.setExcludes('weekends,monday,tuesday,wednesday,thursday'); + expect(() => ganttDb.getTasks()).not.toThrow(); + }); + it('should maintain the order in which tasks are created', function () { ganttDb.setAccTitle('Project Execution'); ganttDb.setDateFormat('YYYY-MM-DD');
Vulnerability mechanics
AI mechanics synthesis has not run for this CVE yet.
References
6- github.com/advisories/GHSA-6m6c-36f7-fhxhghsaADVISORY
- github.com/mermaid-js/mermaid/commit/a59ea56174712ee5430dfd5bc877cb5151f501a6ghsaWEB
- github.com/mermaid-js/mermaid/commit/faafb5d49106dd32c367f3882505f2dd625aa30eghsaWEB
- github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0ghsaWEB
- github.com/mermaid-js/mermaid/releases/tag/v10.9.6ghsaWEB
- github.com/mermaid-js/mermaid/security/advisories/GHSA-6m6c-36f7-fhxhghsaWEB
News mentions
0No linked articles in our index yet.