Back to Blog
high SEVERITY7 min read

How Denial of Service via Regular Expression Happens in Node.js Dependencies and How to Fix It

A high-severity denial of service vulnerability in the `path-to-regexp` package (CVE-2026-4926) could allow attackers to craft malicious regular expressions that consume excessive CPU resources. The fix upgrades from version 8.2.0 to 8.4.0, which hardens regex handling and prevents ReDoS (Regular Expression Denial of Service) attacks in Express applications.

O
By Orbis AppSec
Published August 21, 2026Reviewed August 21, 2026

Answer Summary

CVE-2026-4926 is a Regular Expression Denial of Service (ReDoS) vulnerability in the path-to-regexp Node.js package used by Express for route matching. Versions prior to 8.4.0 are susceptible to crafted regex patterns that cause catastrophic backtracking, freezing the application. The fix involves upgrading path-to-regexp from 8.2.0 to 8.4.0, which implements safer regex compilation and pattern validation to prevent malicious input from triggering exponential time complexity.

Vulnerability at a Glance

cweCWE-1333 (Inefficient Regular Expression Complexity)
fixUpgrade path-to-regexp to 8.4.0 with improved regex compilation logic
riskApplication hang/crash when processing specially crafted URL patterns
languageJavaScript (Node.js)
root causeVulnerable regex engine in path-to-regexp 8.2.0 susceptible to catastrophic backtracking
vulnerabilityRegular Expression Denial of Service (ReDoS) in path-to-regexp

How Denial of Service via Regular Expression Happens in Node.js Dependencies and How to Fix It

Introduction

In a production Express application, the path-to-regexp package is responsible for parsing and matching HTTP request routes. This library converts URL path patterns into compiled regular expressions that the Express router uses to determine which handler should process each incoming request. However, version 8.2.0 of path-to-regexp contained a critical flaw: its regex compilation logic was vulnerable to Regular Expression Denial of Service (ReDoS) attacks through CVE-2026-4926.

An attacker could craft a malicious URL pattern that, when processed by the vulnerable regex engine, would trigger catastrophic backtracking—causing the regex matcher to enter an exponential time loop that consumes 100% CPU and freezes the entire application. For applications handling dynamic route registration or accepting route patterns from configuration files, this vulnerability created a direct denial of service vector.

The Vulnerability Explained

What is ReDoS?

Regular Expression Denial of Service (ReDoS) occurs when a regex engine processes input that causes it to backtrack exponentially through the pattern matching logic. Most regex engines use backtracking algorithms that, when faced with certain nested quantifiers or overlapping patterns, can attempt an astronomical number of combinations before determining a match failure.

In the case of path-to-regexp 8.2.0, the vulnerability existed in how the library compiled route patterns into regex expressions. The library accepts path patterns like /users/:id and converts them into JavaScript RegExp objects. If the pattern construction logic didn't properly escape or validate certain character sequences, an attacker could inject patterns that, when compiled, produced regexes with catastrophic backtracking characteristics.

The Attack Vector

Consider a vulnerable Express application using path-to-regexp 8.2.0:

// app.js - vulnerable code
const express = require('express');
const app = express();

// If an attacker can influence route registration...
app.get(userControlledPattern, (req, res) => {
  res.send('Route handler');
});

An attacker could provide a pattern like:

/api/(a+)+b

This pattern contains nested quantifiers (a+ inside ()+). When the regex engine tries to match a long string of 'a' characters followed by something other than 'b', it enters catastrophic backtracking:
- The outer + tries to match one or more groups of a+
- Each group can match a different number of 'a's
- When the final character isn't 'b', the engine backtracks through all possible combinations
- With a 30-character string, this can result in 2^30 (over 1 billion) attempts

The result: the application freezes, unable to process any requests until the regex operation completes (which may never happen).

Real-World Impact

In the context of this application:

  1. Route Registration Vulnerability: If the application dynamically registers routes from external configuration, an attacker could inject a malicious pattern
  2. Request Handling Freeze: Even a single malicious request could hang the entire Express server
  3. Cascading Failure: In a microservices architecture, one frozen service could cause timeouts across dependent services
  4. Resource Exhaustion: The CPU spike from ReDoS could trigger autoscaler events, causing unnecessary infrastructure costs

The Fix

The fix involved upgrading path-to-regexp from version 8.2.0 to 8.4.0. Let's examine the specific changes in the dependency files:

Before (Vulnerable)

"path-to-regexp": {
  "version": "8.2.0",
  "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
  "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
  "engines": {
    "node": ">=16"
  }
}

After (Fixed)

"path-to-regexp": {
  "version": "8.4.0",
  "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.0.tgz",
  "integrity": "sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg==",
  "funding": {
    "type": "opencollective",
    "url": "https://opencollective.com/express"
  }
}

What Changed in 8.4.0?

The path-to-regexp 8.4.0 release includes several critical improvements:

  1. Improved Regex Compilation: The regex generation logic now includes safeguards against patterns that could trigger catastrophic backtracking
  2. Input Validation: Route patterns are now validated during compilation to reject or sanitize sequences that could create vulnerable regexes
  3. Bounded Quantifiers: The library now limits or transforms nested quantifiers that could cause exponential backtracking
  4. Safer Escaping: Special characters and quantifiers are more carefully escaped during the pattern-to-regex conversion process

The actual code improvements in 8.4.0 (from the upstream path-to-regexp repository) include:
- Refactored regex token generation with explicit checks for problematic patterns
- Implementation of regex complexity analysis before compilation
- Stricter handling of wildcard and parameter matching logic

Also Updated: package.json Constraint

Additionally, the fix updated the version constraint in package.json:

- "path-to-regexp": "^8.0.0"
+ "path-to-regexp": "8.4.0"

Changing from a caret constraint (^8.0.0, which allows any version ≥8.0.0 and <9.0.0) to a pinned version (8.4.0) ensures that:
1. The patched version is always used
2. Accidental downgrades during dependency resolution are prevented
3. The application doesn't automatically pull in potentially vulnerable intermediate versions

Prevention & Best Practices

1. Keep Dependencies Updated

Regularly update your dependencies, especially security-critical packages like routing libraries:

npm audit
npm audit fix
npm update

Enable automated dependency scanning in your CI/CD pipeline using tools like Dependabot or Snyk.

2. Use Security Scanners

Integrate vulnerability scanners that detect known vulnerable versions:

# Using Trivy (as used in the original PR detection)
trivy fs package-lock.json

# Using npm audit
npm audit

# Using Snyk
snyk test

3. Implement Request Timeouts

Add timeout protection to catch ReDoS attacks:

const express = require('express');
const app = express();

// Set request timeout
app.use((req, res, next) => {
  req.setTimeout(5000); // 5 second timeout
  next();
});

4. Validate Route Patterns

If your application accepts dynamic route patterns, validate them:

// Reject patterns with nested quantifiers
function isValidRoutePattern(pattern) {
  // Reject nested quantifiers like (a+)+, (a*)+, etc.
  if (/\([^)]*[*+]\)[*+]/.test(pattern)) {
    return false;
  }
  return true;
}

if (isValidRoutePattern(userPattern)) {
  app.get(userPattern, handler);
} else {
  throw new Error('Invalid route pattern');
}

5. Use Security Standards

Reference these resources for ReDoS prevention:
- OWASP: Regular Expression Denial of Service
- CWE-1333: Inefficient Regular Expression Complexity
- CWE-185: Incorrect Regular Expression

Key Takeaways

  • Nested quantifiers in regex patterns ((a+)+) are a ReDoS red flag: The vulnerability in path-to-regexp 8.2.0 could be triggered by patterns with nested quantifiers that caused exponential backtracking in the regex engine.

  • Pinning critical dependency versions prevents accidental downgrades: The fix changed the constraint from ^8.0.0 to 8.4.0, ensuring the patched version is always used and intermediate vulnerable versions are skipped.

  • Dynamic route registration is a security risk if patterns aren't validated: Applications accepting user-controlled route patterns must validate them to prevent ReDoS injection, as demonstrated by this vulnerability's attack surface.

  • Security scanners like Trivy can detect vulnerable dependency versions automatically: The original detection of CVE-2026-4926 came from Trivy scanning package-lock.json, showing that automated tools are essential for supply chain security.

  • Timeout protection is a defense-in-depth measure against ReDoS: Even if a vulnerable version somehow runs, request timeouts can prevent complete application freeze by interrupting long-running regex operations.

How Orbis AppSec Detected This

Source: Dependency manifest scanning (package-lock.json) identifying the vulnerable path-to-regexp@8.2.0 package version

Sink: The path-to-regexp library's regex compilation function, which processes route patterns and generates RegExp objects susceptible to catastrophic backtracking when handling malicious patterns

Missing Control: No validation of regex complexity or pattern structure before compilation; no bounds on quantifier nesting; no timeout protection on regex matching operations

CWE: CWE-1333 (Inefficient Regular Expression Complexity)

Fix: Upgrade path-to-regexp from 8.2.0 to 8.4.0, which implements improved regex compilation with safeguards against catastrophic backtracking patterns, and pin the version constraint to prevent accidental downgrades.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-4926 demonstrates how even widely-used, well-maintained libraries can contain subtle vulnerabilities in complex logic like regular expression compilation. The ReDoS attack surface in path-to-regexp 8.2.0 could have allowed attackers to freeze Express applications with a single crafted request—a critical denial of service risk.

The fix—upgrading to version 8.4.0 and pinning the dependency version—eliminates this vulnerability by implementing safer regex compilation logic. However, this incident underscores the importance of:

  1. Continuous dependency monitoring using automated security scanners
  2. Timely patching of vulnerable dependencies, even when updates seem minor
  3. Defense-in-depth practices like request timeouts and pattern validation
  4. Supply chain security as a core part of your application security strategy

By staying vigilant about dependency vulnerabilities and promptly applying patches, you significantly reduce the attack surface of your applications and protect them from ReDoS and other supply chain attacks.


References

Frequently Asked Questions

What is a Regular Expression Denial of Service (ReDoS)?

ReDoS is an attack where specially crafted input strings cause regex engines to enter catastrophic backtracking, consuming CPU exponentially and freezing the application. In path-to-regexp, malicious route patterns could trigger this behavior.

How do you prevent ReDoS in Node.js applications?

Keep dependencies updated, use security scanners like Trivy to detect vulnerable versions, implement request timeouts, validate route patterns, and avoid user-controlled regex compilation without sanitization.

What CWE is ReDoS?

CWE-1333 (Inefficient Regular Expression Complexity) and CWE-185 (Incorrect Regular Expression) are the primary classifications for ReDoS vulnerabilities.

Is input validation alone enough to prevent ReDoS in path-to-regexp?

No. While input validation helps, the core issue is in the regex engine itself. Upgrading to a patched version that implements safer regex compilation is essential.

Can static analysis detect ReDoS vulnerabilities?

Yes. Tools like Trivy, Snyk, and npm audit can detect known vulnerable versions. However, detecting ReDoS patterns in custom regexes requires specialized regex analysis tools.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #29

Related Articles

critical

How Command Injection via Unescaped Line Terminators Happens in Node.js and How to Fix It

A critical command injection vulnerability (CVE-2026-9277) was discovered in the shell-quote npm package version 1.8.3, where unescaped line terminators could allow attackers to execute arbitrary code. This fix upgrades shell-quote to version 1.9.0 using npm overrides to ensure all instances in the dependency tree are patched, eliminating the attack vector across the entire application.

critical

How Distributed Lock Takeover Happens in Node.js and How to Fix It

A critical vulnerability in `redis-lock/server.mjs` allowed any authenticated client to release another client's lock by guessing predictable holder identifiers like process IDs or hostnames. The fix implements cryptographically random `lockId` values that are minted on lock acquisition and validated on release, eliminating the exploit primitive entirely.

high

How Denial of Service via Infinite Loop happens in JavaScript (nanoid) and how to fix it

A high-severity denial of service vulnerability (CVE-2026-67213) was discovered in nanoid versions before 5.1.6 and 3.3.18, where the `customAlphabet` function could enter an infinite loop during random ID generation. The fix upgrades the transitive nanoid dependency from 3.3.16 to 3.3.18 using pnpm overrides, ensuring the vulnerable code path is eliminated from the entire dependency tree including PostCSS.

high

How Information Disclosure via Unstripped Credential Headers Happens in Electron Apps and How to Fix It

A high-severity vulnerability (CVE-2026-54673) in the builder-util-runtime package allowed sensitive credential headers to leak during HTTP redirects in Electron applications. The fix upgrades builder-util-runtime from version 9.5.1 to 9.7.0, which properly strips authentication headers before following redirects to prevent information disclosure.

high

How Command Injection happens in PHP and how to fix it

A high-severity command injection vulnerability was discovered in `lib/Controller/Helper.php` where the `corruptline()` method used `exec()` to run sed and awk commands with user-controlled input. The fix replaced all shell command execution with native PHP file operations using `SplFileObject`, eliminating the command injection attack surface entirely.

high

How Missing CSRF Middleware happens in Express.js and how to fix it

A high-severity CSRF vulnerability was discovered in `libProxy.js` of an Express.js application — the app had no CSRF middleware protecting its state-changing routes, leaving them open to cross-site request forgery attacks. The fix introduces a `csrf` token library, a `/csrf-token` endpoint to issue tokens, and a middleware that validates `x-csrf-token` headers or `_csrf` body fields on all non-safe HTTP methods. This proactive hardening removes an exploit primitive that could be chained with ot