Back to Blog
high SEVERITY6 min read

How Denial of Service via Inefficient Route Matching happens in React Router and how to fix it

CVE-2026-55685 is a high-severity Denial of Service vulnerability in React Router (versions prior to 7.18.0) that allows unauthenticated attackers to exhaust server resources through crafted requests to the manifest endpoint. The fix upgrades react-router from 7.16.0 to 8.3.0, which eliminates the inefficient route matching logic and removes the vulnerable `set-cookie-parser` dependency entirely.

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

Answer Summary

CVE-2026-55685 is a high-severity Denial of Service (DoS) vulnerability in React Router (JavaScript/TypeScript) related to CWE-400 (Uncontrolled Resource Consumption). Unauthenticated attackers can send crafted requests to the server-side manifest endpoint, triggering inefficient route matching that exhausts CPU resources. The fix is to upgrade react-router to version 7.18.0 or later (in this case, 8.3.0), which restructures route matching logic and removes the vulnerable code path.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade react-router from 7.16.0 to 8.3.0 (which includes the CVE-2026-55685 patch)
riskUnauthenticated attackers can crash or freeze the server by sending crafted manifest requests
languageJavaScript/TypeScript (Node.js)
root causeInefficient algorithmic complexity in route matching on the unauthenticated manifest endpoint
vulnerabilityDenial of Service via Inefficient Route Matching

Introduction

In the frontend dependency tree of this application, a high-severity Denial of Service vulnerability lurked in react-router version 7.16.0. CVE-2026-55685 exposes a critical flaw: the server-side manifest endpoint in React Router accepts unauthenticated requests and processes them through an inefficient route matching algorithm. An attacker doesn't need credentials—just a carefully crafted HTTP request—to pin the server's CPU at 100% and render the application unavailable to all users.

The vulnerability was flagged by Trivy in frontend/package-lock.json, specifically targeting the react-router dependency and its transitive dependency chain including cookie and set-cookie-parser. The fix involves a major version upgrade that restructures how React Router handles manifest requests internally.

The Vulnerability Explained

What's the Manifest Endpoint?

React Router's server-side rendering (SSR) mode exposes an internal manifest endpoint that clients use to fetch route metadata for client-side navigation. This endpoint is, by design, unauthenticated—it needs to be accessible to any browser loading the application.

The Algorithmic Problem

In react-router 7.16.0, the manifest endpoint processes incoming route patterns through a matching algorithm with poor worst-case complexity. When an attacker sends a request with a specially crafted URL path containing nested or repetitive segments, the route matcher enters a pathological case where it performs exponential backtracking—similar to ReDoS (Regular Expression Denial of Service) but at the route matching level.

The vulnerable version's dependency tree looked like this:

"node_modules/react-router": {
  "version": "7.16.0",
  "dependencies": {
    "cookie": "^1.0.1",
    "set-cookie-parser": "^2.6.0"
  },
  "engines": {
    "node": ">=20.0.0"
  },
  "peerDependencies": {
    "react": ">=18",
    "react-dom": ">=18"
  }
}

The set-cookie-parser dependency was part of the server-runtime handling that processed these manifest requests, parsing cookies from incoming requests before route matching occurred—meaning the vulnerable code path was reachable without any authentication check.

Attack Scenario

An attacker could exploit this vulnerability with a simple script:

# Repeated crafted requests to the manifest endpoint
for i in $(seq 1 100); do
  curl -s "https://target-app/__manifest?path=/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a" &
done

Each request triggers the inefficient route matching, and because the endpoint is unauthenticated, there's no barrier to sending thousands of these requests. Even a modest number of concurrent requests could saturate the server's CPU, causing:

  1. Complete application unavailability for legitimate users
  2. Cascading failures in microservice architectures where the frontend server becomes unresponsive
  3. Potential infrastructure costs from auto-scaling triggered by the CPU spike

The Fix

The fix upgrades react-router from version 7.16.0 to 8.3.0, which includes the patch for CVE-2026-55685. This isn't just a minor patch—it's a significant restructuring of how React Router handles server-side requests.

Before (Vulnerable)

"node_modules/react-router": {
  "version": "7.16.0",
  "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.16.0.tgz",
  "dependencies": {
    "cookie": "^1.0.1",
    "set-cookie-parser": "^2.6.0"
  },
  "engines": {
    "node": ">=20.0.0"
  },
  "peerDependencies": {
    "react": ">=18",
    "react-dom": ">=18"
  }
}

After (Fixed)

"node_modules/react-router": {
  "version": "8.3.0",
  "resolved": "https://registry.npmjs.org/react-router/-/react-router-8.3.0.tgz",
  "dependencies": {
    "cookie-es": "^3.1.1"
  },
  "engines": {
    "node": ">=22.22.0"
  },
  "peerDependencies": {
    "react": ">=19.2.7",
    "react-dom": ">=19.2.7"
  }
}

Key Changes

  1. set-cookie-parser removed entirely: The vulnerable request processing pipeline that included set-cookie-parser has been eliminated. The new version no longer needs this dependency, reducing the attack surface.

  2. cookie replaced with cookie-es: The cookie package (v1.1.1) was replaced with cookie-es (v3.1.1), a more modern, ESM-native cookie handling library. This change is part of the broader refactoring that fixed the manifest endpoint handling.

  3. Engine requirement bumped to Node.js ≥22.22.0: The new version leverages more recent Node.js features for efficient request processing, indicating the route matching internals were significantly rewritten.

  4. React peer dependency updated to ≥19.2.7: The fix is part of a broader modernization that ensures compatibility with the latest React features for server-side rendering.

The cookie dependency change from cookie to cookie-es is particularly telling:

// REMOVED
"node_modules/cookie": {
  "version": "1.1.1",
  "engines": { "node": ">=18" }
}

// ADDED
"node_modules/cookie-es": {
  "version": "3.1.1"
}

The cookie-es library is lighter and doesn't carry the same server-runtime baggage that was part of the vulnerable code path.

Prevention & Best Practices

1. Monitor Dependencies Continuously

This vulnerability existed in a transitive dependency chain. The application didn't directly call the vulnerable code—React Router's internal server-side handling did. Continuous scanning with tools like Trivy catches these issues before they're exploited.

2. Rate Limit All Endpoints

Even internal endpoints like /__manifest should have rate limiting. While this doesn't fix the root cause, it provides defense-in-depth:

// Example: Rate limiting the manifest endpoint
app.use('/__manifest', rateLimit({
  windowMs: 1000,
  max: 10,
  message: 'Too many requests'
}));

3. Pin and Audit Major Dependencies

React Router is a core routing dependency. Pin it to specific versions and audit upgrades:

// package.json - pin exact version
"react-router": "8.3.0"

4. Use Lockfile Scanning in CI/CD

Add dependency scanning to your CI pipeline to catch vulnerable packages before they reach production:

# Example CI step
- name: Scan dependencies
  run: trivy fs --scanners vuln frontend/package-lock.json

5. Understand Your Attack Surface

Unauthenticated endpoints are prime targets. Audit which endpoints in your SSR framework are publicly accessible and ensure they have appropriate protections against abuse.

Key Takeaways

  • React Router's manifest endpoint is unauthenticated by design, making algorithmic inefficiency in route matching a direct DoS vector—always consider the authentication context of framework-internal endpoints.
  • The set-cookie-parser dependency removal indicates the fix restructured the entire request processing pipeline, not just patched the route matching—sometimes the best fix is architectural.
  • Transitive dependencies (cookie, set-cookie-parser) contributed to the vulnerable code path even though the application never directly imported them—lockfile scanning is essential.
  • The Node.js engine requirement jump from ≥20.0.0 to ≥22.22.0 signals significant internal changes—verify your deployment environment supports the new requirements before upgrading.
  • Even "internal" framework endpoints like /__manifest need DoS protection—attackers don't respect the boundary between "public" and "internal" URLs.

How Orbis AppSec Detected This

  • Source: Unauthenticated HTTP requests to the React Router server-side manifest endpoint (/__manifest)
  • Sink: Inefficient route matching algorithm in react-router@7.16.0's server runtime, processing attacker-controlled URL path segments
  • Missing control: No computational complexity bounds on route matching for unauthenticated manifest requests; no rate limiting or input length validation on the path parameter
  • CWE: CWE-400 (Uncontrolled Resource Consumption)
  • Fix: Upgraded react-router from 7.16.0 to 8.3.0 in frontend/package-lock.json, which replaces the inefficient route matching implementation and removes the set-cookie-parser dependency from the vulnerable code path.

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-55685 is a stark reminder that Denial of Service vulnerabilities don't require authentication bypass or data exfiltration to be severe. A single unauthenticated endpoint with inefficient algorithmic behavior can bring down an entire application. The fix—upgrading from react-router 7.16.0 to 8.3.0—eliminates the vulnerable code path entirely by restructuring how manifest requests are processed and removing unnecessary dependencies like set-cookie-parser.

For teams using React Router with server-side rendering, this upgrade should be prioritized. The change in peer dependencies (React ≥19.2.7) and engine requirements (Node.js ≥22.22.0) means this isn't a drop-in patch, but the security improvement justifies the migration effort. Always scan your lockfiles, understand which endpoints are unauthenticated, and treat algorithmic complexity as a security concern.

References

Frequently Asked Questions

What is Denial of Service via Inefficient Route Matching?

It's a vulnerability where an attacker sends specially crafted requests that trigger computationally expensive route matching algorithms, consuming excessive CPU time and making the server unresponsive to legitimate users.

How do you prevent Denial of Service via route matching in JavaScript?

Keep routing libraries updated, implement rate limiting on all endpoints (including internal ones like manifest endpoints), and use algorithmic complexity analysis to ensure route matching scales linearly with input size.

What CWE is Denial of Service via Inefficient Route Matching?

CWE-400 (Uncontrolled Resource Consumption), which covers scenarios where software does not properly control the allocation and maintenance of limited resources, allowing attackers to exhaust those resources.

Is rate limiting enough to prevent this type of DoS?

Rate limiting helps reduce the attack surface but is not sufficient alone—the underlying algorithmic inefficiency must be fixed, as even a small number of crafted requests could consume disproportionate resources before rate limits kick in.

Can static analysis detect Denial of Service via Inefficient Route Matching?

Yes, tools like Trivy can flag known vulnerable dependency versions via CVE databases, and specialized tools can detect algorithmic complexity issues, though runtime profiling is often needed to confirm exploitability.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #554

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