{"id":"GHSA-w739-gvwx-grc3","revision":null,"records":[{"revision":"92d2f648d5774f45993fd4e42b931042","observedAt":"2026-11-03T22:57:17.07+00:00","statement":{"source":"cve-program","id":"CVE-2026-111754","aliases":[],"title":"Angular: Open Redirect via Protocol-Relative URLs in Server-Side Rendering (SSR)","description":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.33, 21.2.25, and 22.2.1, ServerPlatformLocation in Angular server-side rendering checks for protocol-relative URLs before WHATWG URL normalization. A request path containing a popping dot segment followed by multiple slashes can bypass the raw resolveUrl check and normalize to a pathname beginning with two slashes. When Angular SSR detects a mismatch with the router's final location, it can place that pathname in an HTTP Location header, causing a browser to navigate to an attacker-controlled origin. Affected applications use @angular/platform-server and @angular/ssr and either expose compatible parameter or child route shapes or pass user-controlled navigation targets through infrastructure that preserves the relevant dot segments or semicolons. Pure client-side SPAs are not affected. This issue is fixed in versions 20.3.33, 21.2.25, and 22.2.1.","state":0,"publishedAt":"2026-11-03T20:55:11.497+00:00","modifiedAt":"2026-11-03T21:23:55.644+00:00","affected":[{"ecosystem":"Vendor product","name":"angular","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"angular\",\n                    \"product\": \"angular\",\n                    \"versions\": [\n                        {\n                            \"version\": \"<= 19.2.25\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 20.0.0, < 20.3.33\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 21.0.0, < 21.2.25\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 22.0.0, < 22.2.1\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","score":5.1,"severity":"MEDIUM"}],"references":["https://github.com/angular/angular/security/advisories/GHSA-w739-gvwx-grc3","https://github.com/angular/angular/issues/71076","https://github.com/angular/angular/pull/71077","https://github.com/angular/angular/pull/71078","https://github.com/angular/angular/pull/71079","https://github.com/angular/angular/commit/450af9c813c7660b9bd91e5635f705ee3ed7b32a","https://github.com/angular/angular/commit/83944fc8c50e86be90e8ec4184cd15002b5af262","https://github.com/angular/angular/commit/928dcfd2582152655b5559509d057bf6a5a19521","https://github.com/angular/angular/releases/tag/v20.3.33","https://github.com/angular/angular/releases/tag/v21.2.25","https://github.com/angular/angular/releases/tag/v22.2.1"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-111754","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-111754","identifiers":["CVE-2026-111754"]},"retained":false,"historicalAffected":[]},{"revision":"bd5194f1d27948d6a26b9ddbf6c13bed","observedAt":"2026-11-07T04:32:49.241+00:00","statement":{"source":"euvd","id":"EUVD-2026-116377","aliases":["CVE-2026-111754","GHSA-w739-gvwx-grc3"],"title":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.33, 21.2.25, and 22.2.1, ServerPlatformLocation in Angular server-side rendering checks for pr…","description":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.33, 21.2.25, and 22.2.1, ServerPlatformLocation in Angular server-side rendering checks for protocol-relative URLs before WHATWG URL normalization. A request path containing a popping dot segment followed by multiple slashes can bypass the raw resolveUrl check and normalize to a pathname beginning with two slashes. When Angular SSR detects a mismatch with the router's final location, it can place that pathname in an HTTP Location header, causing a browser to navigate to an attacker-controlled origin. Affected applications use @angular/platform-server and @angular/ssr and either expose compatible parameter or child route shapes or pass user-controlled navigation targets through infrastructure that preserves the relevant dot segments or semicolons. Pure client-side SPAs are not affected. This issue is fixed in versions 20.3.33, 21.2.25, and 22.2.1.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","score":5.1,"severity":null}],"references":["https://github.com/angular/angular/security/advisories/GHSA-w739-gvwx-grc3","https://github.com/angular/angular/issues/71076","https://github.com/angular/angular/pull/71077","https://github.com/angular/angular/pull/71078","https://github.com/angular/angular/pull/71079","https://github.com/angular/angular/commit/450af9c813c7660b9bd91e5635f705ee3ed7b32a","https://github.com/angular/angular/commit/83944fc8c50e86be90e8ec4184cd15002b5af262","https://github.com/angular/angular/commit/928dcfd2582152655b5559509d057bf6a5a19521","https://github.com/angular/angular/releases/tag/v20.3.33","https://github.com/angular/angular/releases/tag/v21.2.25","https://github.com/angular/angular/releases/tag/v22.2.1"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-116377","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Nov 3, 2026, 8:55:11 PM","dateUpdated":"Nov 3, 2026, 9:23:55 PM"},"relatedAdvisories":[],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-116377","identifiers":["EUVD-2026-116377","CVE-2026-111754","GHSA-w739-gvwx-grc3"]},"retained":false,"historicalAffected":[]},{"revision":"fd7ae7de61844fd29115a305fc014615","observedAt":"2026-11-04T08:57:34.019+00:00","statement":{"source":"nvd","id":"CVE-2026-111754","aliases":[],"title":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.33, 21.2.25, and 22.2.1, ServerPlatformLocation in Angular server-side rendering checks for pr…","description":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.33, 21.2.25, and 22.2.1, ServerPlatformLocation in Angular server-side rendering checks for protocol-relative URLs before WHATWG URL normalization. A request path containing a popping dot segment followed by multiple slashes can bypass the raw resolveUrl check and normalize to a pathname beginning with two slashes. When Angular SSR detects a mismatch with the router's final location, it can place that pathname in an HTTP Location header, causing a browser to navigate to an attacker-controlled origin. Affected applications use @angular/platform-server and @angular/ssr and either expose compatible parameter or child route shapes or pass user-controlled navigation targets through infrastructure that preserves the relevant dot segments or semicolons. Pure client-side SPAs are not affected. This issue is fixed in versions 20.3.33, 21.2.25, and 22.2.1.","state":0,"publishedAt":"2026-11-03T21:16:58.203+00:00","modifiedAt":"2026-11-03T22:17:44.523+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · security-advisories@github.com · Secondary","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","score":5.1,"severity":"MEDIUM"}],"references":["https://github.com/angular/angular/commit/450af9c813c7660b9bd91e5635f705ee3ed7b32a","https://github.com/angular/angular/commit/83944fc8c50e86be90e8ec4184cd15002b5af262","https://github.com/angular/angular/commit/928dcfd2582152655b5559509d057bf6a5a19521","https://github.com/angular/angular/issues/71076","https://github.com/angular/angular/pull/71077","https://github.com/angular/angular/pull/71078","https://github.com/angular/angular/pull/71079","https://github.com/angular/angular/releases/tag/v20.3.33","https://github.com/angular/angular/releases/tag/v21.2.25","https://github.com/angular/angular/releases/tag/v22.2.1","https://github.com/angular/angular/security/advisories/GHSA-w739-gvwx-grc3"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-111754","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Received","weaknesses":["CWE-601"],"productCriteria":[],"sourceDates":{"published":"2026-11-03T21:16:58.203","lastModified":"2026-11-03T22:17:44.523"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-111754","identifiers":["CVE-2026-111754"]},"retained":false,"historicalAffected":[]},{"revision":"a415b0fe8f8345bab14454af442261b2","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-w739-gvwx-grc3","aliases":["CVE-2026-111754"],"title":"@angular/platform-server: Open Redirect via Protocol-Relative URLs in Server-Side Rendering (SSR)","description":"An open redirect vulnerability was identified in `@angular/platform-server` when Server-Side Rendering (SSR) is enabled.\n\nWhen 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.\n\nWhen 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`).\n\nConsequently, `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.\n\n### Impact\n\nSuccessful exploitation allows an unauthenticated remote attacker to craft URLs that trick Angular SSR into redirecting users to an arbitrary external domain.\n\n* **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.\n* **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.\n\n### Attack Preconditions & Vulnerable Configurations\n\nAn application is affected if the following conditions are met:\n\n* **SSR Enabled:** The application runs in a Server-Side Rendering environment using `@angular/platform-server` and `@angular/ssr`.\n* **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`).\n* **Reverse Proxy Passthrough:** Upstream reverse proxies (Nginx, Cloudflare, ALB) pass semicolons (`;`) or dot-segments without stripping or normalizing them.\n\n#### Exploit Payload Example\n\nAn attacker sends a request targeting a route with parameters and child segments:\n\n```http\nGET /.;/(//evil.test) HTTP/1.1\nHost: example.com\n```\n\n**Response:**\n```http\nHTTP/1.1 302 Found\nLocation: //evil.test\n```\n\nThe client browser resolves `//evil.test` protocol-relatively and redirects the user away from `example.com` to `evil.test`.\n\n### Patches\n\nThe 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`.\n\n* `22.2.1`\n* `21.2.25`\n* `20.3.33`\n\n### Workarounds & Mitigations\n\nIf you cannot immediately upgrade to a patched version, apply one of the following mitigations at your edge reverse proxy or WAF:\n\n1. **Reject Paths with Dot-Segments Followed by Slashes:**\n   Configure your reverse proxy (e.g., Nginx, Cloudflare, AWS WAF) to block requests containing `/.//`, `/..//`, or `/.;/`:\n   ```nginx\n   # Nginx example: reject suspicious path normalization sequences\n   if ($request_uri ~* \"(\\n/\\.\\/|\\/\\.\\;)\") {\n       return 400;\n   }\n   ```\n2. **Sanitize Redirect Headers:**\n   Ensure edge proxies or API gateways rewrite or disallow protocol-relative (`//`) `Location` response headers originating from the SSR upstream.","state":0,"publishedAt":"2026-10-20T14:35:49+00:00","modifiedAt":"2026-10-20T14:45:03.7713496+00:00","affected":[{"ecosystem":"npm","name":"@angular/platform-server","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"22.0.0"},{"kind":"fixed","version":"22.2.1"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"npm","name":"@angular/platform-server","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"21.0.0"},{"kind":"fixed","version":"21.2.25"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"npm","name":"@angular/platform-server","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"20.0.0"},{"kind":"fixed","version":"20.3.33"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"npm","name":"@angular/platform-server","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"last_affected","version":"19.2.25"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V4","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/angular/angular/security/advisories/GHSA-w739-gvwx-grc3","https://github.com/angular/angular/pull/71077","https://github.com/angular/angular/pull/71078","https://github.com/angular/angular/pull/71079","https://github.com/angular/angular/commit/450af9c813c7660b9bd91e5635f705ee3ed7b32a","https://github.com/angular/angular/commit/83944fc8c50e86be90e8ec4184cd15002b5af262","https://github.com/angular/angular/commit/928dcfd2582152655b5559509d057bf6a5a19521","https://github.com/angular/angular/commit/d7d81e189d227108c3b9d39178dbb7389f6f970d","https://github.com/angular/angular","https://github.com/angular/angular/releases/tag/v20.3.33","https://github.com/angular/angular/releases/tag/v21.2.25","https://github.com/angular/angular/releases/tag/v22.2.1"],"sourceUrl":"https://github.com/advisories/GHSA-w739-gvwx-grc3","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-w739-gvwx-grc3","identifiers":["GHSA-w739-gvwx-grc3","CVE-2026-111754"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-08T13:04:23.5160344+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-08T13:04:23.5160344+00:00","lastSuccessAt":"2026-11-08T13:04:23.701507+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:23.7015079+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-eaa64dac63caa79c8d4905619258c41c51b39e461b996124e1a21b5e85e7e738-5e9a1b25b88c72db8d3c46be95e52009e07ae4af884484ac8e34e4d7f79f07eb","complete":true,"records":421098,"lastAttemptAt":"2026-11-08T13:04:23.0585244+00:00","lastSuccessAt":"2026-11-08T13:04:23.0353669+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:23.0585244+00:00","snapshotPublishedAt":"2026-11-08T12:20:14+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-383c643166b94ac4b6a615647191978e","complete":true,"records":13654,"lastAttemptAt":"2026-11-08T13:04:50.0771652+00:00","lastSuccessAt":"2026-11-08T13:04:50.073+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:50.073+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13706,"expectedIdentifiers":13706,"failedIdentifiers":0},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-08T13:04:23.5160344+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-08T13:04:23.5160344+00:00","lastSuccessAt":"2026-11-08T13:04:23.7022986+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:23.7022987+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-d0adb98f65b04a798dd6ab08fb972092","complete":false,"records":13666,"lastAttemptAt":"2026-11-08T13:04:49.0861553+00:00","lastSuccessAt":"2026-11-08T13:04:49.083+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:49.083+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13185,"expectedIdentifiers":13706,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-980593e6977a6d1b4fb1eed5a1ffe88a468736f89f0a06f710924ad59132c023","complete":true,"records":9914,"lastAttemptAt":"2026-11-08T13:04:23.3678903+00:00","lastSuccessAt":"2026-11-08T11:07:07.068788+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:23.3678903+00:00","snapshotPublishedAt":"2026-11-08T11:02:46+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-fde804134ecdda0ddd5ff5c26ee1fff5a6fa659311f7ef2e51c6ad54964db0e2","complete":true,"records":1971,"lastAttemptAt":"2026-11-08T13:04:23.1502223+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:23.1502223+00:00","snapshotPublishedAt":"2026-11-06T18:17:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-964c14035e6f0f6478b2870fad6a7ef9f6045876d4a12af2c2e514521e54b6af","complete":true,"records":3055,"lastAttemptAt":"2026-11-08T13:04:23.4767311+00:00","lastSuccessAt":"2026-11-08T11:07:12.1927025+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:23.4767311+00:00","snapshotPublishedAt":"2026-11-08T11:02:46+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-f8647d7ba64b1ba0dfdc7130944766d5b36d5b77d18fff0c79e651a4cff3c2b9","complete":true,"records":231293,"lastAttemptAt":"2026-11-08T13:04:23.2659134+00:00","lastSuccessAt":"2026-11-08T11:06:56.2918717+00:00","error":null,"lastVerifiedAt":"2026-11-08T13:04:23.2659134+00:00","snapshotPublishedAt":"2026-11-08T11:02:50+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}