---
id: "CVE-2026-111754"
kind: "vulnerability"
aliases: ["CVE-2026-111754", "GHSA-w739-gvwx-grc3"]
title: "@angular/platform-server: Open Redirect via Protocol-Relative URLs in Server-Side Rendering (SSR)"
severity: "medium"
cvss: null
epss: null
exploited: false
status: "open"
category: "package"
products: [{"name": "@angular/platform-server", "fixed": ["22.2.1"], "affected": ">= 22.0.0, < 22.2.1", "ecosystem": "npm"}, {"name": "@angular/platform-server", "fixed": ["21.2.25"], "affected": ">= 21.0.0, < 21.2.25", "ecosystem": "npm"}, {"name": "@angular/platform-server", "fixed": ["20.3.33"], "affected": ">= 20.0.0, < 20.3.33", "ecosystem": "npm"}, {"name": "@angular/platform-server", "fixed": [], "affected": "<= 19.2.25", "ecosystem": "npm"}]
ecosystems: ["npm"]
tags: ["angular", "angular-ssr", "cwe-601", "next.js-alternative", "node", "package", "self-hosted"]
not_affected_if: ["client-side-only", "managed-hosting", "no-ssr"]
published_at: "2026-10-20T14:35:49+00:00"
first_seen_at: "2026-10-23T19:11:32+00:00"
updated_at: "2026-10-23T20:13:40+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-w739-gvwx-grc3", "first_seen_at": "2026-10-23T19:11:32+00:00"}]
---

# @angular/platform-server: Open Redirect via Protocol-Relative URLs in Server-Side Rendering (SSR)

An Angular SSR app built on @angular/platform-server can be made to answer an attacker-crafted URL such as /.;/(//evil.test) with a 302 whose Location header is //evil.test, sending the browser off-origin. This is an open redirect that can bypass naive returnUrl checks that only look for a leading '//'.

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

## Affected

- npm:@angular/platform-server affected >= 22.0.0, < 22.2.1 fixed 22.2.1
- npm:@angular/platform-server affected >= 21.0.0, < 21.2.25 fixed 21.2.25
- npm:@angular/platform-server affected >= 20.0.0, < 20.3.33 fixed 20.3.33
- npm:@angular/platform-server affected <= 19.2.25 fixed ?

## How to check

Check the installed version: npm ls @angular/platform-server
Confirm SSR is in use: @angular/ssr present in package.json
Send GET /.;/(//evil.test) to the app and look for a 302 with Location: //evil.test

## Fix

Upgrade @angular/platform-server to 22.2.1, 21.2.25, or 20.3.33 (the fixed version for your release line).
Until patched, block /.// , /..// and /.;/ at the edge proxy or WAF, and strip or reject protocol-relative Location headers from the SSR upstream.

## Timeline

- 2026-10-23T19:11:32+00:00 ghsa https://github.com/advisories/GHSA-w739-gvwx-grc3

## From the sources

An open redirect vulnerability was identified in `@angular/platform-server` when Server-Side Rendering (SSR) is enabled.

When Angular SSR renders an incoming request, URL resolution and platform navigation are managed by `ServerPlatformLocation` using `resolveUrl` (or `parseUrl` in v20). While `resolveUrl` rejected protocol-relative URLs whose raw string directly started with `//`, this check ran *prior* to WHATWG URL normalization.

When a request URL includes a popping dot-segment followed by multiple slashes (such as `/.//evil.test` or serialized from router route shapes like `/.;/(//evil.test)`), the input bypassed the initial `urlStr.startsWith('//')` check. Subsequent WHATWG URL parsing resolved the dot-segments and resulted in a `pathname` starting with `//` (`//evil.test`).

Consequently, `ServerPlatformLocation` stored `pathname = '//evil.test'`. When `@angular/ssr` detected a mismatch between the rendered URL and the router's final location state, it emitted the unnormalized pathname into the HTTP `Location` response header, producing an HTTP 302 redirect with `Location: //evil.test`, which browsers resolve as a protocol-relative navigation off-origin.

### Impact

Successful exploitation allows an unauthenticated remote attacker to craft URLs that trick Angular SSR into redirecting users to an arbitrary external domain.

* **Bypasses Application-Level Guards:** Common application-level validation routines (such as checking `!returnUrl.startsWith('//')` before invoking `router.navigateByUrl`) accept `/.//evil.test` or `/.;/(//evil.test)` as a safe relative path, allowing attackers to bypass redirect allowlists.
* **Client-side SPAs Unaffected:** Pure client-side Angular applications (Single Page Applications without SSR) are **not** vulnerable, as `ServerPlatformLocation` is only utilized in server-side execution environments.

### Attack Preconditions & Vulnerable Configurations

An application is affected if the following conditions are met:

* **SSR Enabled:** The application runs in a Server-Side Rendering environment using `@angular/platform-server` and `@angular/ssr`.
* **Parameter Route Shapes:** The router contains parameter routes with wildcard or child segments (e.g. `/:tenant` matching `.` and serializing secondary outlet groups `(//evil.test)` to `/.//evil.test`), or passes user-provided navigation targets (e.g. `returnUrl`).
* **Reverse Proxy Passthrough:** Upstream reverse proxies (Nginx, Cloudflare, ALB) pass semicolons (`;`) or dot-segments without stripping or normalizing them.

#### Exploit Payload Example

An attacker sends a request targeting a route with parameters and child segments:

```http
GET /.;/(//evil.test) HTTP/1.1
Host: example.com
```

**Response:**
```http
HTTP/1.1 302 Found
Location: //evil.test
```

The client browser resolves `//evil.test` protocol-relatively and redirects the user away from `example.com` to `evil.test`.

### Patches

The issue is resolved by updating `resolveUrl` (and `parseUrl` in v20) in `@angular/platform-server` to verify that the normalized URL pathname does not start with `//` when `allowProtocolRelative` is `false`.

* `22.2.1`
* `21.2.25`
* `20.3.33`

### Workarounds & Mitigations

If you cannot immediately upgrade to a patched version, apply one of the following mitigations at your edge reverse proxy or WAF:

1. **Reject Paths with Dot-Segments Followed by Slashes:**
   Configure your reverse proxy (e.g., Nginx, Cloudflare, AWS WAF) to block requests containing `/.//`, `/..//`, or `/.;/`:
   ```nginx
   # Nginx example: reject suspicious path normalization sequences
   if ($request_uri ~* "(\n/\.\/|\/\.\;)") {
       return 400;
   }
   ```
2. **Sanitize Redirect Headers:**
   Ensure edge proxies or API gateways rewrite or disallow protocol-relative (`//`) `Location` response headers originating from the SSR upstream.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
