CVE-2026-111752
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Angular is a TypeScript-based web development platform for building scalable single-page and server-side rendered applications. It provides a modular architecture, powerful dependency injection, and built-in tools for building modern, performant, and maintainable applications across web, mobile, and desktop environments.
A Denial of Service (DoS) vulnerability (CVE-2026-111752) has been identified in the @angular/router package, which allows unauthenticated remote attackers to exhaust the Node.js heap or CPU of a Server-Side Rendered (SSR) application with crafted URLs containing unconfigured auxiliary outlet segments. When the matched routes declare canMatch guards or resolvers, a short crafted URL can also run those guards and resolvers many times, adding load on backend services.
Per OWASP: The Denial of Service (DoS) attack is focused on making a resource (site, application, server) unavailable for the purpose it was designed. There are many ways to make a service unavailable for legitimate users by manipulating network packets, programming, logical, or resources handling vulnerabilities, among others. If a service receives a very large number of requests, it may cease to be available to legitimate users. In the same way, a service may stop if a programming vulnerability is exploited, or the way the service handles resources it uses.
This issue affects multiple versions of Angular.
Details
Module Info
- Product: Angular
- Affected packages:
@angular/router - Affected versions:
- <=19.2.25
- >=20.0.0 <20.3.33
- >=21.0.0 <21.2.25
- >=22.0.0 <22.2.1
- GitHub repository: https://github.com/angular/angular
- Published packages: https://www.npmjs.com/package/@angular/router
- Package manager: npm
- Fixed in:
- OSS Angular v20.3.33, v21.2.25, v22.2.1
- NES for Angular v19.2.32, v18.2.28, v17.3.28, v16.2.28
Vulnerability Info
This High-severity vulnerability is found in the @angular/router package in multiple versions of Angular. Only applications that render on demand on a Node.js server are exposed; client-side applications and build-time prerendering do not process attacker-supplied request URLs. The application must also have at least one empty-path (path: '') route or one route assigned to a named outlet.
During route recognition, the Recognizer walks every outlet the URL names, including auxiliary outlets such as a:/() that no route is configured for. Each one is matched against the whole route configuration at that level:
return from(childOutlets).pipe(
concatMap((childOutlet) => {
const child = segmentGroup.children[childOutlet];
const sortedConfig = sortByMatchingOutlets(config, childOutlet);
return this.processSegmentGroup(injector, sortedConfig, child, childOutlet, parentRoute);
}),
scan((children, outletChildren) => {
children.push(...outletChildren);
return children;
}),A route declared for a different outlet is still allowed to match whenever it has an empty path:
if (
getOutlet(route) !== outlet &&
(outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))
) {
return noMatch(rawSegment);
}Nothing checks that the outlet segment group matched a route configured for its own outlet. So an empty-path route, or a named-outlet route, matches every arbitrary outlet group in the URL. Each match builds its own ActivatedRouteSnapshot with a fresh copy of the URL's query parameters (Object.freeze({...this.urlTree.queryParams})), runs that route's canMatch guards, and recurses into processChildren whenever the group still has children. Nested empty-path outlet groups therefore multiply the work. The noLeftoversInUrl check (segments.length === 0 && !segmentGroup.children[outlet]) lets these matches complete, and the duplicate-outlet check that could reject them, checkOutletNameUniqueness, only runs in development mode (ngDevMode).
The advisory gives two example request shapes. The first works against empty-path routes with query parameters, and the second against named-outlet routes:
GET /shop/(a:/()//b:/()//c:/()//...)?param1=value¶m2=value... HTTP/1.1
GET /dashboard/(detail:1//x:/(detail:1//x:/(...)//y:/(...))//y:/(...)) HTTP/1.1The memory is released when route recognition finishes, so there is no persistent leak. However, a single request near the Node.js default 16 KiB header limit, or a few concurrent ones, can push a worker with a constrained heap into a fatal JavaScript heap out-of-memory crash, which terminates the SSR worker process.
Mitigation
Angular versions prior to 20 were already End-of-Life when this CVE was published and will not receive any updates to address this issue. For more information see here.
Users of the affected components should apply one of the following mitigations:
- Migrate affected applications to a patched version of Angular.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.