The flaw is in the retrieveSSGPage logic of CommonEngine, in @angular/ssr/node and earlier versions of @angular/ssr. When an application passes an attacker-controlled relative URL to CommonEngine.render, the URL can contain a backslash parent-traversal segment on Windows.
The relevant sequence is:
- The non-special
resolve:// URL base preserves the backslash in the pathname.
- On Windows,
path.join treats the backslash as a path separator, allowing the constructed path to move from publicPath into a sibling directory.
- The
pagePath.startsWith(normalize(publicPath)) check performs a prefix comparison without requiring a trailing directory separator. A sibling directory whose name begins with the configured public-directory prefix can therefore pass the check.
- If the target file exists and contains the Angular SSG marker,
CommonEngine reads and returns that prerendered page instead of rendering the requested route.
The required deployment conditions are Windows hosting, use of CommonEngine, a relative request URL, a prefix-sharing sibling output directory, and qualifying prerendered HTML containing the Angular SSG marker. The exact route layout and page content of an individual application are not established by the available evidence.