CVE-2026-24001
High · 7.5CVSS
7.5
EPSS
0.6%
Published
Jan 22, 2026
CISA due date
—
Cloudanix analysis
A small specially crafted patch or filename can crash affected applications that process text differences, causing service interruptions.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Low
- Impact
- Denial Of Service
- Component
- Library
- Class
- Denial of service
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
This vulnerability affects the jsdiff JavaScript library when applications call parsePatch on patch text, or call applyPatch with a string patch that is parsed internally. Malformed patch filename headers containing carriage return (\r), Unicode line separator (\u2028), or Unicode paragraph separator (\u2029) can cause parsePatch to enter an infinite loop and consume memory until the Node.js process crashes. A related regular-expression denial-of-service condition can also occur when the same characters appear in the patch header or leading garbage, causing parsing time to grow roughly O(n³). The flaw does not provide code execution, data theft, or privilege escalation; the primary impact is application availability loss.
Why it matters to the business
An unauthenticated remote attacker may be able to crash services that accept or process patch/diff content, including code review, merge, source-control, CI/CD, and developer-platform workflows that depend on jsdiff or downstream packages. Because a small payload can trigger the issue, request-size limits alone are not an effective control. The CVSS score is high for availability impact, but current public exploitation signals are limited: it is not listed in CISA KEV, is not associated with ransomware use, has low EPSS probability, and has no known mature exploit reported in the supplied data. Organizations should still remediate because the vulnerable code may be embedded transitively in widely deployed developer tooling and container images.
How an attack unfolds
An attacker first identifies an application endpoint, API, webhook, upload feature, repository operation, or background job that accepts patch text or allows user-controlled filenames that are later embedded into a generated patch. The attacker submits a syntactically crafted patch whose filename header includes one of the problematic line break characters, such as carriage return, Unicode line separator, or Unicode paragraph separator. When the application passes that content to jsdiff parsePatch, or to applyPatch with a string patch, the parser fails to progress correctly and loops while allocating memory. The affected Node.js process experiences sustained CPU and memory pressure and can terminate with an out-of-memory condition. Depending on deployment architecture, this may cause a single request worker, service container, CI job, or entire application instance to restart or become unavailable. A secondary attack path uses the same special characters in the patch header or leading garbage to cause excessive parser runtime rather than immediate memory exhaustion.
How to fix it
Upgrade jsdiff to a fixed release appropriate for the major version in use: 8.0.3 or later, 5.2.2 or later, 4.0.4 or later, or 3.5.1 or later. If consuming the upstream Git repository directly, ensure the dependency includes commit 13576bfbcc444ce48f71cfd1e08529bd13962411 or a later fixed commit. For the listed GitLab MinimOS 18.3 packages, upgrade to 18.3.4-r0 or later for the affected components, including gitlab-cng, gitlab-base, gitlab-shell, gitaly-config, gitlab-container-registry, gitlab-exporter, gitlab-logger, related scripts, certificates, pages scripts, and compatibility packages. Regenerate lockfiles and rebuild container images so transitive copies of jsdiff are actually replaced. As a temporary mitigation, reject or sanitize patch input and user-controlled filenames containing \r, \u2028, or \u2029 before calling parsePatch or applyPatch. Do not rely only on maximum upload or request size, because small payloads can trigger the issue. Add runtime resource controls such as process memory limits, worker isolation, request timeouts, and automatic restarts to reduce blast radius, but treat these as compensating controls rather than a fix.
How to confirm the fix worked
Confirm dependency resolution shows a fixed jsdiff version in package-lock.json, npm-shrinkwrap.json, yarn.lock, pnpm-lock.yaml, SBOMs, and deployed artifacts. Run npm ls diff jsdiff, yarn why diff/jsdiff, pnpm why diff/jsdiff, or equivalent software composition analysis to identify direct and transitive instances. For containerized deployments, scan rebuilt images and verify affected GitLab MinimOS packages report 18.3.4-r0 or later. Review application code for parsePatch and applyPatch usage and verify untrusted patch strings or user-controlled filenames are either no longer passed to vulnerable versions or are filtered for \r, \u2028, and \u2029. In a safe non-production environment, run regression tests with patch filename headers containing those characters and confirm parsing is rejected quickly or handled without unbounded CPU or memory growth. Monitor after rollout for absence of Node.js out-of-memory crashes tied to patch parsing workflows.
Typical attack path
- Locate an exposed feature that accepts patches, diffs, repository metadata, uploaded text, or filenames used to generate diffs.
- Confirm or infer that the backend uses a vulnerable jsdiff version before 8.0.3, 5.2.2, 4.0.4, or 3.5.1, or a downstream package/container that embeds it.
- Send a small malicious patch containing \r, \u2028, or \u2029 in a filename header, or supply a filename that causes those characters to appear in a generated patch header.
- Trigger application logic that calls parsePatch, or applyPatch with a string patch argument.
- Cause the parser to loop or spend excessive time parsing, resulting in increasing memory and/or CPU usage.
- Crash or degrade the affected process, potentially causing service interruption, job failure, container restart, or denial of service.
How to detect it
Look for evidence of denial-of-service attempts against endpoints or jobs that accept patch, diff, merge, repository, code review, or file-comparison input. Relevant sources include application access logs, API gateway and WAF logs, reverse proxy logs, Node.js application logs, process supervisor logs, container runtime and Kubernetes events, CI/CD job logs, and APM metrics. Search for requests containing patch-style headers such as --- and +++ where the filename portion includes carriage returns or encoded Unicode line/paragraph separators. Review crashes around the same time for Node.js heap exhaustion, process restarts, SIGABRT, SIGKILL, OOMKilled, memory cgroup kills, elevated garbage collection, or CPU saturation. Inspect uploaded patch artifacts, request bodies retained by logging systems, job workspaces, and temporary files for filename headers containing raw or encoded \r, \u2028, or \u2029. If exploitation is suspected, correlate the source IP, account, token, repository operation, user agent, and request path with repeated crashes or timeouts. There are no known threat actors or ransomware campaigns associated with the supplied data, so detection should focus on behavioral signs and malformed patch content rather than actor-specific infrastructure.
- FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
- FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
- JavaScript heap out of memory
- Allocation failed - JavaScript heap out of memory
- OOMKilled
- memory cgroup out of memory
- Killed process node
- SIGABRT
- SIGKILL
- parsePatch
- applyPatch
- ---
- +++
- %E2%80%A8
- %E2%80%A9
- \u2028
- \u2029
- %0D
What your security team should do
- Prioritize upgrading jsdiff and any downstream images or packages that bundle it, especially internet-facing services and developer platforms that process user-submitted patches or diffs.
- Inventory all applications for parsePatch and applyPatch usage, including transitive dependencies and container images, because vulnerable behavior may be reachable indirectly.
- Add input validation at service boundaries to reject \r, \u2028, and \u2029 in patch filename headers and user-controlled filenames used to generate diffs.
- Do not consider file-size, request-size, or upload-size limits sufficient mitigation; the trigger can be small.
- Apply memory limits, CPU quotas, request timeouts, worker isolation, and restart policies to reduce denial-of-service blast radius while remediation is underway.
- Create monitoring alerts for sudden Node.js memory growth, heap out-of-memory errors, container OOMKilled events, repeated worker restarts, and spikes around patch/diff parsing endpoints.
- Because this is not currently KEV-listed and EPSS is low, schedule as high-priority availability remediation rather than emergency incident response unless exposure is internet-facing or supports critical workflows.
The record
jsdiff is a JavaScript text differencing implementation. Prior to versions 8.0.3, 5.2.2, 4.0.4, and 3.5.1, attempting to parse a patch whose filename headers contain the line break characters `\r`, `\u2028`, or `\u2029` can cause the `parsePatch` method to enter an infinite loop. It then consumes memory without limit until the process crashes due to running out of memory. Applications are therefore likely to be vulnerable to a denial-of-service attack if they call `parsePatch` with a user-provided patch as input. A large payload is not needed to trigger the vulnerability, so size limits on user input do not provide any protection. Furthermore, some applications may be vulnerable even when calling `parsePatch` on a patch generated by the application itself if the user is nonetheless able to control the filename headers (e.g. by directly providing the filenames of the files to be diffed). The `applyPatch` method is similarly affected if (and only if) called with a string representation of a patch as an argument, since under the hood it parses that string using `parsePatch`. Other methods of the library are unaffected. Finally, a second and lesser interdependent bug - a ReDOS - also exhibits when those same line break characters are present in a patch's *patch* header (also known as its "leading garbage"). A maliciously-crafted patch header of length *n* can take `parsePatch` O(*n*³) time to parse. Versions 8.0.3, 5.2.2, 4.0.4, and 3.5.1 contain a fix. As a workaround, do not attempt to parse patches that contain any of these characters: `\r`, `\u2028`, or `\u2029`.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| npm | diff | 0 | 3.5.1 |
| npm | diff | 4.0.0 | 4.0.4 |
| npm | diff | 5.0.0 | 5.2.2 |
| npm | diff | 6.0.0 | 8.0.3 |
| Chainguard | actions-runner | 0 | 2.331.0-r1 |
| Chainguard | argo-workflows-ui-3.6 | 0 | 3.6.17-r0 |
| Chainguard | argo-workflows-ui-3.7 | 0 | 3.7.8-r0 |
| Chainguard | code-server | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.10 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.8 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.9 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.8 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.9 | 0 | 0 |
| Chainguard | graalvm-24-ce-nodejs | 0 | 24.0.2-r8 |
| Chainguard | graalvm-25-ce-nodejs | 0 | 25.0.1-r2 |
| Chainguard | graalvm-25-ce-nodejs | 0 | 25.0.1-r3 |
| Chainguard | grafana-12.1 | 0 | 12.1.5-r2 |
| Chainguard | grafana-12.1 | 0 | 12.1.6-r0 |
| Chainguard | grafana-fips-12.1 | 0 | 12.1.6-r0 |
| Chainguard | langfuse-2-worker | 0 | 2.95.12-r6 |
| Chainguard | langfuse-3-worker | 0 | 3.146.0-r2 |
| Chainguard | langfuse-fips-2-worker | 0 | 2.95.12-r6 |
| Chainguard | langfuse-fips-3-worker | 0 | 3.147.0-r1 |
| Chainguard | librechat | 0 | 0.8.1-r5 |
| Chainguard | npm | 0 | 11.8.0-r0 |
| Chainguard | prism | 0 | 5.14.3-r2 |
| Chainguard | redisinsight | 0 | 3.0.2-r1 |
| Chainguard | renovate | 0 | 43.2.4-r0 |
| Chainguard | tileserver-gl | 0 | 5.5.0-r2 |
| Chainguard | tileserver-gl-fips | 0 | 5.5.0-r3 |
| Chainguard | vitess-22 | 0 | 22.0.3-r0 |
| Chainguard | vitess-23 | 0 | 23.0.1-r0 |
| Wolfi | argo-workflows-ui-3.7 | 0 | 3.7.8-r0 |
| Wolfi | code-server | 0 | 0 |
| Wolfi | grafana-12.1 | 0 | 12.1.5-r2 |
| Wolfi | grafana-12.1 | 0 | 12.1.6-r0 |
| Wolfi | langfuse-3-worker | 0 | 3.146.0-r2 |
| Wolfi | npm | 0 | 11.8.0-r0 |
| Wolfi | prism | 0 | 5.14.3-r2 |
| Wolfi | renovate | 0 | 43.2.4-r0 |
| Wolfi | tileserver-gl | 0 | 5.5.0-r2 |
| Wolfi | vitess-22 | 0 | 22.0.3-r0 |
| Wolfi | vitess-23 | 0 | 23.0.1-r0 |
Related vulnerabilities
- GHSA-73rr-hh4g-fpgx jsdiff has a Denial of Service vulnerability in parsePatch and applyPatch Same vulnerability
- GHSA-h6ch-v84p-w6p9 Regular Expression Denial of Service (ReDoS) Also affects diff
- GHSA-9ppj-qmqm-q256 node-tar Symlink Path Traversal via Drive-Relative Linkpath Also affects actions-runner
- CVE-2026-31802 node-tar is a full-featured Tar for Node.js. Also affects actions-runner
- CVE-2026-29786 node-tar is a full-featured Tar for Node.js. Also affects actions-runner
- GHSA-qffp-2rhf-9h96 tar has Hardlink Path Traversal via Drive-Relative Linkpath Also affects actions-runner
- GHSA-7r86-cg39-jmmj minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent… Also affects actions-runner
- GHSA-23c5-xmqv-rm74 minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regular… Also affects actions-runner