Back to Blog
high SEVERITY7 min read

How ReDoS happens in Node.js path-to-regexp and how to fix it

CVE-2024-52798 is a Regular Expression Denial of Service (ReDoS) vulnerability in the `path-to-regexp` package's 0.1.x branch, which remains unpatched in that legacy line. Because `path-to-regexp` is a transitive dependency pulled in by `websocket-driver` and many other popular Node.js packages, any application that processes attacker-controlled URL paths through an affected version is at risk of catastrophic backtracking that can freeze the event loop. Upgrading `websocket-driver` to 0.7.5 — an

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

Answer Summary

CVE-2024-52798 is a Regular Expression Denial of Service (ReDoS) vulnerability (CWE-1333) in the `path-to-regexp` npm package, specifically its legacy 0.1.x branch. An attacker can craft a malicious URL string that causes the regex engine to backtrack exponentially, blocking Node.js's single-threaded event loop and causing a denial of service. The fix is to upgrade the transitive dependency chain so that the vulnerable `path-to-regexp` 0.1.x version is no longer resolved — in this case by upgrading `websocket-driver` from 0.7.4 to 0.7.5 and adding a `"websocket-driver": "0.7.5"` override in `package.json`.

Vulnerability at a Glance

cweCWE-1333 (Inefficient Regular Expression Complexity)
fixUpgrade `websocket-driver` to 0.7.5 and add a package override to evict the vulnerable `path-to-regexp` 0.1.x transitive dependency
riskAttacker-crafted URL strings can freeze the Node.js event loop, causing full application denial of service
languageJavaScript / Node.js
root causeThe `path-to-regexp` 0.1.x regex contains catastrophically backtracking patterns when matching certain malformed path strings
vulnerabilityRegular Expression Denial of Service (ReDoS)

The Hidden Danger in Your Dependency Tree

The backend/package-lock.json file in this project quietly pulls in path-to-regexp as a transitive dependency — meaning no developer explicitly installed it, yet it sits in the resolved dependency tree and runs in production. When security scanner Trivy flagged CVE-2024-52798, it revealed that the version of path-to-regexp being resolved belonged to the unpatched 0.1.x branch — a legacy line that contains a catastrophically backtracking regular expression with no upstream fix planned for that branch.

This is the uncomfortable reality of modern JavaScript development: your node_modules folder contains hundreds of packages you never consciously chose, and any one of them can introduce a critical vulnerability. In this case, the attack surface is a regex that processes URL path strings — exactly the kind of input that flows in from the internet.


The Vulnerability Explained

What is path-to-regexp?

path-to-regexp is a utility that converts Express-style route strings like /users/:id into regular expressions for URL matching. It's one of the most downloaded npm packages ever, used under the hood by Express.js, Koa, and many other frameworks and tools.

The ReDoS Problem in 0.1.x

CVE-2024-52798 describes a Regular Expression Denial of Service (ReDoS) flaw in the path-to-regexp 0.1.x branch. The root cause is a regex pattern that exhibits catastrophic backtracking — a phenomenon where the regex engine's attempt to find a match causes it to explore an exponentially growing number of possible paths through the input string.

A simplified illustration of the kind of pattern that causes this:

// Vulnerable pattern (conceptual illustration of catastrophic backtracking)
const re = /^(\w+\s?)*$/;

// Benign input — matches instantly
re.test("hello world");

// Malicious input — causes exponential backtracking
re.test("aaaaaaaaaaaaaaaaaaaaaaaaaaaa!");

In path-to-regexp 0.1.x, the generated regex for certain route patterns contains nested quantifiers that interact badly with malformed path strings. An attacker who can influence the URL path being matched — for example, by sending a crafted HTTP request — can trigger this backtracking.

Why Node.js Is Especially Vulnerable

Node.js runs JavaScript on a single-threaded event loop. Unlike multi-threaded servers that can isolate a slow request to one thread, a ReDoS attack in Node.js blocks all request processing for the duration of the backtracking. A single malicious HTTP request can render the entire application unresponsive.

The Vulnerable Dependency Chain

The vulnerable version was pulled in transitively through websocket-driver 0.7.4:

websocket-driver@0.7.4
  └── websocket-extensions (which resolves path-to-regexp@0.1.x)

The package-lock.json before the fix resolved:

"node_modules/websocket-driver": {
  "version": "0.7.4",
  "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
  "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg=="
}

This older version of websocket-driver depended on a sub-dependency that resolved path-to-regexp into the vulnerable 0.1.x range.

Attack Scenario

Consider a WebSocket handshake endpoint in this application. The websocket-driver package processes the HTTP Upgrade request, and internally path-to-regexp 0.1.x is used to match the request path. An attacker sends a stream of HTTP Upgrade requests with carefully crafted paths:

GET /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!!! HTTP/1.1
Connection: Upgrade
Upgrade: websocket

Each request triggers catastrophic backtracking in the regex engine. Because Node.js is single-threaded, the event loop stalls, and legitimate users receive no responses. The server is effectively down — with no memory exhaustion, no crashes, just a frozen process.


The Fix

What Changed

The fix involved two coordinated changes across frontend/package.json and frontend/package-lock.json.

1. package-lock.json — Upgrading the resolved version

 "node_modules/websocket-driver": {
-  "version": "0.7.4",
-  "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
-  "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+  "version": "0.7.5",
+  "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.5.tgz",
+  "integrity": "sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==",
+  "license": "Apache-2.0",

websocket-driver 0.7.5 updates its own dependency chain so that path-to-regexp 0.1.x is no longer resolved. The new integrity hash (sha512-ZL2+3c7...) confirms the package contents have changed and pins the exact safe artifact.

2. package.json — Adding an override to enforce the safe version

 "overrides": {
-  "shell-quote": "1.9.0"
+  "shell-quote": "1.9.0",
+  "websocket-driver": "0.7.5"
 }

This is the critical second step. npm's overrides field forces all resolutions of websocket-driver in the dependency tree — direct and transitive — to use version 0.7.5. Without this override, a future npm install could potentially re-resolve an older version if another dependency requested it. The override acts as a security policy enforced at the package manager level.

Why Both Changes Are Necessary

The package-lock.json change fixes the current resolved state. The package.json override ensures the fix is durable — it survives future dependency updates and npm install runs by any developer on the team. Together, they provide both an immediate fix and a long-term guard.


Prevention & Best Practices

1. Audit Transitive Dependencies Regularly

Most ReDoS vulnerabilities like CVE-2024-52798 live in packages you didn't install directly. Use tools that scan the full dependency tree:

npm audit
npx trivy fs . --scanners vuln

2. Use overrides (npm) or resolutions (Yarn) as a Security Policy

When a transitive dependency is vulnerable and the direct parent hasn't released a fix yet, package overrides are your best tool:

// package.json
"overrides": {
  "vulnerable-package": ">=safe-version"
}

3. Test Regex Patterns for Catastrophic Backtracking

If you write your own route-matching or path-parsing logic, test your regexes:

# Use safe-regex to detect dangerous patterns
npx safe-regex '/^(\w+\s?)*$/'

4. Consider a ReDoS Timeout Wrapper

For applications that must use regex on user input, consider wrapping execution with a timeout:

const { execSync } = require('child_process');

function safeRegexTest(pattern, input, timeoutMs = 100) {
  // Use a worker thread or subprocess with a timeout
  // rather than running potentially dangerous regex on the main thread
}

5. Follow OWASP and CWE Guidance

  • CWE-1333: Inefficient Regular Expression Complexity — the formal classification for ReDoS
  • OWASP: The OWASP Testing Guide covers denial-of-service testing including ReDoS scenarios
  • OWASP Dependency-Check: Use automated SCA (Software Composition Analysis) in your CI/CD pipeline

Key Takeaways

  • path-to-regexp 0.1.x is permanently vulnerable — there is no patch for the 0.1.x branch. Any project resolving this version is exposed to CVE-2024-52798 until the dependency chain is updated.
  • websocket-driver 0.7.4 was the direct parent pulling in the vulnerable version — upgrading it to 0.7.5 in package-lock.json was the first required step.
  • The package.json override "websocket-driver": "0.7.5" is what makes the fix permanent — without it, the vulnerable version could return after the next npm install.
  • A single malicious HTTP request is enough to trigger this ReDoS and freeze the Node.js event loop, making it a low-effort, high-impact attack.
  • Transitive dependency scanning must be part of your CI pipeline — neither path-to-regexp nor websocket-driver appears in this project's direct dependencies, yet both were present in the resolved tree.

How Orbis AppSec Detected This

  • Source: Attacker-controlled URL path strings arriving via HTTP/WebSocket Upgrade requests processed by websocket-driver
  • Sink: The regex compilation and matching logic inside path-to-regexp 0.1.x, invoked transitively through websocket-driver@0.7.4's dependency chain in frontend/package-lock.json
  • Missing control: No version constraint or override existed to prevent npm from resolving the vulnerable path-to-regexp 0.1.x range; the package.json overrides block did not include websocket-driver
  • CWE: CWE-1333 — Inefficient Regular Expression Complexity
  • Fix: websocket-driver was upgraded from 0.7.4 to 0.7.5 in package-lock.json, and "websocket-driver": "0.7.5" was added to the overrides field in package.json to permanently enforce the safe version across the entire dependency tree

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-2024-52798 is a reminder that the most dangerous vulnerabilities in modern Node.js applications are often ones you never wrote yourself. The path-to-regexp 0.1.x ReDoS flaw lives three levels deep in a dependency tree, invisible to casual inspection, yet capable of taking down a production server with a single crafted request.

The fix here is precise and durable: upgrading websocket-driver to 0.7.5 evicts the vulnerable package version, while the package.json override ensures no future npm install can silently reintroduce it. Both changes together — one in the lock file, one in the manifest — represent the correct, complete approach to remediating transitive dependency vulnerabilities.

For your own projects: run npm audit and a dedicated SCA scanner like Trivy regularly, use overrides as an active security policy, and treat your package-lock.json as a security artifact that deserves the same review attention as your source code.


References

Frequently Asked Questions

What is a ReDoS vulnerability?

ReDoS (Regular Expression Denial of Service) occurs when a regex engine is forced into exponential backtracking by a specially crafted input string, consuming all available CPU and blocking execution — in Node.js, this blocks the entire event loop.

How do you prevent ReDoS in Node.js?

Audit all regex patterns for catastrophic backtracking using tools like `safe-regex` or `vuln-regex-detector`, keep dependencies up to date, and use package overrides to pin transitive dependencies to safe versions.

What CWE is ReDoS?

ReDoS is classified as CWE-1333: Inefficient Regular Expression Complexity.

Is input validation enough to prevent ReDoS?

Not always — if the vulnerable regex is inside a library you don't control, input validation at your application layer may not be sufficient. Upgrading or replacing the vulnerable library is the most reliable fix.

Can static analysis detect ReDoS?

Yes. Tools like Semgrep, ESLint with security plugins, and dedicated ReDoS detectors (e.g., `vuln-regex-detector`) can identify potentially catastrophic regex patterns at development time.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #15

Related Articles

high

How Denial of Service via Crafted Long-Path Tar Archives Happens in Node.js and How to Fix It

CVE-2026-73566 is a Denial of Service vulnerability in node-tar that allows attackers to craft specially malformed tar archives with excessively long file paths to exhaust system resources and crash applications. The fix upgrades tar from version 7.5.19 to 7.5.21, which implements proper path length validation to prevent this attack vector.

high

How Denial of Service via Memory Exhaustion happens in Socket.IO Parser and how to fix it

CVE-2026-69185 is a high-severity Denial of Service vulnerability in the `socket.io-parser` package that allows attackers to exhaust server memory by sending specially crafted packets. The fix upgrades `socket.io-parser` from version 4.2.4 to 4.2.7 (and parallel branches to 3.4.5 and 3.3.6) in `client/package-lock.json`, closing the attack surface against malicious clients. This kind of memory-exhaustion flaw is particularly dangerous in real-time applications where the parser handles a continuo

high

How express-check-csurf-middleware-usage happens in JavaScript/Express and how to fix it

A high-severity CSRF vulnerability was identified in `tower_game/index.js` where the Express application lacked any Cross-Site Request Forgery protection middleware. Without CSRF validation, an attacker could craft malicious pages that trick authenticated users into submitting unwanted requests to the game server. The fix adds `csurf` middleware with cookie-based token storage in just four lines of code.

high

How Quadratic CPU Consumption Happens in js-yaml and How to Fix It

A high-severity denial-of-service vulnerability in js-yaml versions prior to 4.3.1 allowed attackers to craft malicious YAML documents with !!omap tags that triggered quadratic CPU consumption during parsing. This fix upgrades js-yaml from 4.1.1 to 4.3.1 using npm overrides, protecting applications from algorithmic complexity attacks that could freeze or crash Node.js services.

critical

How Denial of Service via Gzip Bomb happens in Node.js and how to fix it

CVE-2026-59873 is a critical Denial of Service vulnerability in node-tar versions prior to 7.5.19, where a maliciously crafted gzip bomb can exhaust server resources when extracting archives. The fix upgrades the `tar` dependency from version 7.5.15 to 7.5.21 in `package-lock.json` and pins the version via an `overrides` block in `package.json`. Any application that processes user-supplied tar archives is at risk of resource exhaustion, making this an urgent upgrade.

high

How trailofbits.python.pickles-in-pytorch.pickles-in-pytorch happens in Python/PyTorch and how to fix it

A high-severity deserialization vulnerability was fixed in `skills/packs/pipeline-phase-5-pretrain-code/scripts/trainer.py` where `torch.save()` was used to serialize model checkpoints. Because PyTorch's save mechanism relies on Python's `pickle` module internally, any checkpoint file loaded later could execute arbitrary code. The fix replaces `torch.save()` with `np.savez()` for model weights and a JSON file for metadata, eliminating the pickle-based serialization entirely.