CVE-2026-104871
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 Path Traversal vulnerability (CVE-2026-104871) has been identified in Angular's Server-Side Rendering Common Engine, which allows attackers to escape the configured public directory on Windows deployments through backslash traversal sequences in the request path and can lead to prerendered pages from sibling build outputs being served to unauthorized users.
Per OWASP: A path traversal attack (also known as directory traversal) aims to access files and directories that are stored outside the web root folder. By manipulating variables that reference files with “dot-dot-slash (../)” sequences and its variations or by using absolute file paths, it may be possible to access arbitrary files and directories stored on file system including application source code or configuration and critical system files.
Details
Module Info
- Product: Angular
- Affected packages:
@angular/ssr - Affected versions:
- <=19.2.27
- >= 20.0.0 < 20.3.36
- >= 21.0.0 < 21.2.23
- >= 22.0.0 < 22.1.7
- GitHub repositories: https://github.com/angular/angular-cli
- Published packages: https://www.npmjs.com/package/@angular/ssr
- Package manager: npm
- Fixed in:
- OSS Angular CLI v22.1.7, v21.2.23, v20.3.36
- NES for Angular CLI v19.2.30, v18.2.28, v17.3.25
- NES for Angular Universal v16.2.3
Vulnerability Info
This Medium-severity vulnerability is found in the @angular/ssr in multiple published versions of Angular.
A Path Traversal vulnerability exists in the prerendered (SSG) page retrieval logic of CommonEngine in @angular/ssr/node (and @angular/ssr in earlier versions). When deployed on Windows, an attacker can craft a request path with backslash directory traversal sequences that causes CommonEngine to serve prerendered pages from sibling output directories.
The vulnerability occurs due to how relative URLs and Windows file paths are resolved and validated. A request URL containing a backslash parent traversal segment (e.g., /..\app-admin) is passed to CommonEngine.render({ url }). The engine parses the URL using new URL(url, 'resolve://'). Because resolve:// is a non-special scheme under the WHATWG URL standard, backslashes are not normalized to forward slashes, leaving the pathname unnormalized as /..\app-admin. The engine then constructs the candidate file path using join(publicPath, pathname, 'index.html'). On Windows, path.join treats \ as a path delimiter, resolving the parent segment (..\) out of publicPath (e.g., dist\app) into a sibling directory (e.g., dist\app-admin\index.html). The containment check (pagePath.startsWith(normalize(publicPath))) performs a prefix match without a trailing path delimiter, so because the sibling folder name starts with the configured public folder name (e.g., dist\app-admin starts with dist\app), the check erroneously succeeds. If the target file exists and contains the Angular SSG marker (ng-server-context="...ssg..."), CommonEngine reads and serves the sibling page instead of rendering the requested route.
This vulnerability allows unauthorized access to prerendered static pages from adjacent applications or build outputs. Prerendered HTML pages located in sibling directories sharing the same name prefix as the public directory, such as an internal administration app app-admin adjacent to app, can be accessed by unauthorized users. The scope is limited in that only HTML files matching the Angular SSG marker regex are served, so arbitrary non-Angular files, secrets, or configuration files without the SSG context attribute cannot be read through this mechanism.
Applications are exposed where CommonEngine from @angular/ssr/node (or @angular/ssr in v17 and v18) is hosted on Windows, where Node's path.join resolves \ as a path separator, and where a relative request URL such as req.url or req.originalUrl without an origin is passed into CommonEngine.render({ url }). The prerendered output of a sibling directory is reachable wherever that directory's name starts with the same prefix as the configured publicPath directory, for example dist\app-admin alongside dist\app, and it contains prerendered HTML carrying the Angular SSG marker.
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.
Credits
- srkyn (Reporter)