---
id: CVE-2026-111754
aliases:
  - GHSA-w739-gvwx-grc3
title: >-
  @angular/platform-server: Open Redirect via Protocol-Relative URLs in
  Server-Side Rendering (SSR)
summary: >-
  @angular/platform-server: Open Redirect via Protocol-Relative URLs in
  Server-Side Rendering (SSR)
severity: medium
cwe:
  - CWE-601
vendor: angular
product: '@angular/platform-server'
ecosystem: npm
affected:
  - '@angular/platform-server >= 22.0.0, < 22.2.1'
  - '@angular/platform-server >= 21.0.0, < 21.2.25'
  - '@angular/platform-server >= 20.0.0, < 20.3.33'
  - '@angular/platform-server <= 19.2.25'
patched:
  - '@angular/platform-server 22.2.1'
  - '@angular/platform-server 21.2.25'
  - '@angular/platform-server 20.3.33'
published: '2026-10-20'
updated: '2026-10-20'
sourceUpdated: '2026-10-20T14:35:51Z'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-w739-gvwx-grc3'
references:
  - url: 'https://github.com/angular/angular/security/advisories/GHSA-w739-gvwx-grc3'
  - url: 'https://github.com/angular/angular/pull/71077'
  - url: 'https://github.com/angular/angular/pull/71078'
  - url: 'https://github.com/angular/angular/pull/71079'
  - url: >-
      https://github.com/angular/angular/commit/450af9c813c7660b9bd91e5635f705ee3ed7b32a
  - url: >-
      https://github.com/angular/angular/commit/83944fc8c50e86be90e8ec4184cd15002b5af262
  - url: >-
      https://github.com/angular/angular/commit/928dcfd2582152655b5559509d057bf6a5a19521
  - url: >-
      https://github.com/angular/angular/commit/d7d81e189d227108c3b9d39178dbb7389f6f970d
  - url: 'https://github.com/angular/angular/releases/tag/v20.3.33'
  - url: 'https://github.com/angular/angular/releases/tag/v21.2.25'
  - url: 'https://github.com/angular/angular/releases/tag/v22.2.1'
  - url: 'https://github.com/advisories/GHSA-w739-gvwx-grc3'
tags:
  - ghsa
  - npm
ingestedAt: '2026-10-20T15:09:24.107Z'
---

## Overview

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.

## Affected packages

- `@angular/platform-server >= 22.0.0, < 22.2.1`
- `@angular/platform-server >= 21.0.0, < 21.2.25`
- `@angular/platform-server >= 20.0.0, < 20.3.33`
- `@angular/platform-server <= 19.2.25`

## Remediation

Upgrade to a patched release:

- `@angular/platform-server 22.2.1`
- `@angular/platform-server 21.2.25`
- `@angular/platform-server 20.3.33`
