---
id: "CVE-2026-101896"
page: "https://infrastack.ai/live/CVE-2026-101896"
kind: "vulnerability"
aliases: ["CVE-2026-101896", "GHSA-ff3f-86qr-9cv3"]
title: "Angular Server-Side Rendering (SSR): Denial of Service via Numeric URL Matrix Parameters"
severity: "high"
cvss: 8.2
epss: 0.00909
exploited: false
status: "open"
category: "package"
products: [{"name": "@angular/router", "fixed": ["22.2.0"], "affected": ">= 22.0.0, < 22.2.0", "ecosystem": "npm"}, {"name": "@angular/router", "fixed": ["21.2.24"], "affected": ">= 21.0.0, < 21.2.24", "ecosystem": "npm"}, {"name": "@angular/router", "fixed": ["20.3.32"], "affected": ">= 20.0.0, < 20.3.32", "ecosystem": "npm"}, {"name": "@angular/router", "fixed": ["End of Support / LTS expired; will not be patched"], "affected": "<= 19.2.25", "ecosystem": "npm"}]
ecosystems: ["npm"]
tags: ["angular", "cwe-400", "cwe-770", "node.js", "npm", "package", "ssr", "web-frontend"]
not_affected_if: ["client-side-only", "proxy-strips-semicolons", "static-export"]
published_at: "2026-09-23T19:02:54+00:00"
first_seen_at: "2026-11-09T22:53:17+00:00"
updated_at: "2026-11-09T22:59:07+00:00"
sources: [{"source": "ghsa-repo", "url": "https://github.com/angular/angular/security/advisories/GHSA-ff3f-86qr-9cv3", "first_seen_at": "2026-11-09T22:53:17+00:00"}, {"source": "ghsa", "url": "https://github.com/advisories/GHSA-ff3f-86qr-9cv3", "first_seen_at": "2026-11-09T22:57:50+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101896", "first_seen_at": "2026-11-09T23:10:12+00:00"}]
exploit_sources: [{"type": "epss", "score": 0.00909, "url": "https://api.first.org/data/v1/epss?cve=CVE-2026-101896"}]
---

# Angular Server-Side Rendering (SSR): Denial of Service via Numeric URL Matrix Parameters

Link for people: https://infrastack.ai/live/CVE-2026-101896 (this .md is for agents)

When Angular SSR runs on Node.js, numeric matrix parameters in request URLs make @angular/router allocate large V8 array backing stores, so a modest number of requests can exhaust the heap. An unauthenticated attacker can crash the server-side rendering worker with an out-of-memory error, causing denial of service.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- npm:@angular/router affected >= 22.0.0, < 22.2.0 fixed 22.2.0
- npm:@angular/router affected >= 21.0.0, < 21.2.24 fixed 21.2.24
- npm:@angular/router affected >= 20.0.0, < 20.3.32 fixed 20.3.32
- npm:@angular/router affected <= 19.2.25 fixed End of Support / LTS expired; will not be patched

## How to check

- Check the installed `@angular/router` version in `package-lock.json` or `yarn.lock`, or run `npm ls @angular/router`.
- Confirm whether the app uses Angular Server-Side Rendering on Node.js.
- Check whether the reverse proxy forwards URLs containing `;` and deep path segments to the SSR service.

## Fix

- `@angular/router` 22.x: upgrade to `22.2.0`
- `@angular/router` 21.x: upgrade to `21.2.24`
- `@angular/router` 20.x: upgrade to `20.3.32`
- `@angular/router` 19.2.25 and older: no fix; the line is out of support and will not be patched

## Timeline

- 2026-11-09T22:53:17+00:00 ghsa-repo https://github.com/angular/angular/security/advisories/GHSA-ff3f-86qr-9cv3
- 2026-11-09T22:57:50+00:00 ghsa https://github.com/advisories/GHSA-ff3f-86qr-9cv3
- 2026-11-09T23:10:12+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-101896

## Documents

- [advisory] Maintainer's advisory: github.com https://github.com/angular/angular/security/advisories/GHSA-ff3f-86qr-9cv3
- [advisory] Maintainer's advisory: api.github.com https://api.github.com/repos/angular/angular/security-advisories/GHSA-ff3f-86qr-9cv3
- [fix] Patch: github.com https://github.com/angular/angular/commit/ddfe21072ba32ca4cd9d7d3c6b7df66af81d58c4
- [fix] Patch: github.com https://github.com/angular/angular/pull/70717
- [fix] Patch: github.com https://github.com/angular/angular/commit/03872a80bcf1c89b2b04cdd3f444b2ee954da583
- [fix] Patch: github.com https://github.com/angular/angular/commit/5af61216eab8bf4a6697a1d79bda3d857c06f89d
- [fix] Release notes: github.com https://github.com/angular/angular/releases/tag/v22.2.0
- [fix] Release notes: github.com https://github.com/angular/angular/releases/tag/v21.2.24
- [fix] Release notes: github.com https://github.com/angular/angular/releases/tag/v20.3.32

## From the sources

A denial of service (DoS) vulnerability was identified in `@angular/router` when Server-Side Rendering (SSR) is enabled on Node.js (V8).

When `@angular/router` parses incoming request URLs, it extracts path segments, matrix parameters, and child outlets into plain JavaScript objects (`Record<string, string>`). When matrix parameter names or outlet names are numeric strings (such as `/a;990;2522`), the V8 JavaScript engine interprets them as array-indexed properties rather than named properties.

Under V8's internal property-storage heuristics, setting numeric keys on an initially empty object causes V8 to allocate a dense array backing store (`HOLEY_ELEMENTS`) sized to the maximum index rather than falling back to sparse dictionary storage. Specifically, assigning sequential or moderately large numeric keys (like `990` followed by `2522`) causes V8 to allocate a contiguous backing store of ~2,522 pointers (~20 KB to 25 KB of heap) for a single 11-byte segment.

Because each segment in a URL path allocates its own independent `parameters` object, an attacker can craft URLs with repeated numeric matrix parameters to achieve an asymmetric memory amplification factor of approximately **~350x**.

### Impact

Successful exploitation allows an unauthenticated remote attacker to exhaust the Node.js old-space heap with modest request volume, terminating the SSR worker with an unrecoverable `JavaScript heap out of memory` fatal error and causing a Denial of Service.

* **High Amplification:** A single 11-byte segment (`/a;990;2522`) consumes ~20 KB–25 KB of V8 heap.
* **Low Concurrency Required:**
  * With 8 KB request paths (~740 segments, within default Nginx 8 KB buffer limits), as few as **12–22 concurrent requests** crash a 256 MiB–512 MiB Node.js SSR worker.
  * With smaller 1 KB–2 KB request paths (~90–180 segments), a burst of ~50–100 concurrent requests achieves the same heap exhaustion.
* **Client-side SPAs Unaffected:** Pure client-side Angular applications (Single Page Applications without SSR) are **not** vulnerable, as local browser memory consumption does not cross a security boundary.

### Attack Preconditions & Vulnerable Configurations

An application is affected only if **all** of the following conditions are met:

* **SSR Enabled:** The application runs in a Server-Side Rendering environment powered by Node.js / V8.
* **Direct Router Parsing:** User-controlled request URLs are parsed by `@angular/router` during SSR.
* **No Reverse-Proxy Semicolon/Segment Filtering:** Upstream reverse proxies (Nginx, Cloudflare, ALB) forward URLs containing semicolons (`;`) and multiple path segments without stripping or rejecting them.

#### Exploit Payload Example

An attacker sends concurrent HTTP requests with repeated numeric matrix parameters:

```http
GET /a;990;2522/a;990;2522/a;990;2522/... HTTP/1.1
Host: example.com
```

Even with paths under 2 KB, overlapping requests during SSR will rapidly consume the V8 heap until the process crashes.

### Patches

The issue is resolved by updating `@angular/router` to enforce V8 dictionary elements storage (`setUrlDerivedKey`) for numeric URL-derived keys (index >= 32). This prevents V8 from allocating oversized contiguous array backing stores while preserving route matching, parameter values, and component input bindings.

* `22.2.0`
* `21.2.24`
* `20.3.32`

### Workarounds & Mitigations

If you cannot immediately upgrade to a patched version, apply one of the following mitigations at your edge or reverse proxy:

1. **Block or Sanitize Matrix Parameters at the Reverse Proxy:**  
   Configure your reverse proxy (e.g., Nginx, Cloudflare, or AWS WAF) to reject or strip semicolons (`;`) in request paths before forwarding requests to the Angular SSR service:
   ```nginx
   # Nginx example: reject requests containing matrix parameters
   if ($uri ~* ";") {
       return 400;
   }
   ```
2. **Enforce Strict Path Segment Limits:**  
   Reject requests with excessive path depth (e.g., more than 20–30 segments).
3. **Increase Node.js Old Space:**  
   Increase `--max-old-space-size` (e.g., to 2048 or 4096 MB) to increase the concurrency threshold required to exhaust memory, though this does not fully eliminate the vulnerability under sustained traffic.

### References

* **Issue:** [angular/angular#70716](https://github.com/angular/angular/issues/70716)
* **Fix PR:** [angular/angular#70717](https://github.com/angular/angular/pull/70717)

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
