Angular has XSS Vulnerability via Unsanitized SVG Script Attributes
Description
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to versions 19.2.18, 20.3.16, 21.0.7, and 21.1.0-rc.0, a cross-site scripting (XSS) vulnerability has been identified in the Angular Template Compiler. The vulnerability exists because Angular’s internal sanitization schema fails to recognize the href and xlink:href attributes of SVG <script> elements as a Resource URL context. This issue has been patched in versions 19.2.18, 20.3.16, 21.0.7, and 21.1.0-rc.0.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@angular/compilernpm | >= 21.1.0-next.0, < 21.1.0-rc.0 | 21.1.0-rc.0 |
@angular/corenpm | >= 21.1.0-next.0, < 21.1.0-rc.0 | 21.1.0-rc.0 |
@angular/compilernpm | >= 21.0.0-next.0, < 21.0.7 | 21.0.7 |
@angular/corenpm | >= 21.0.0-next.0, < 21.0.7 | 21.0.7 |
@angular/compilernpm | >= 20.0.0-next.0, < 20.3.16 | 20.3.16 |
@angular/corenpm | >= 20.0.0-next.0, < 20.3.16 | 20.3.16 |
@angular/compilernpm | >= 19.0.0-next.0, < 19.2.18 | 19.2.18 |
@angular/corenpm | >= 19.0.0-next.0, < 19.2.18 | 19.2.18 |
@angular/compilernpm | <= 18.2.14 | — |
@angular/corenpm | <= 18.2.14 | — |
Affected products
1Patches
191dc91bae4a1fix(core): sanitize sensitive attributes on SVG script elements
4 files changed · +44 −12
packages/compiler-cli/test/ngtsc/ngtsc_spec.ts+28 −0 modified@@ -8611,6 +8611,34 @@ runInEachFileSystem((os: string) => { expect(trim(jsContents)).toContain(trim(hostBindingsFn)); }); + it('should generate sanitizers for URL properties in SVG script fn in Component', () => { + env.write( + 'test.ts', + ` + import {Component} from '@angular/core'; + + @Component({ + selector: 'test-cmp', + template: \` + <svg> + <script [attr.xlink:href]="attr" [attr.href]="attr"></script> + </svg> + \`, + }) + export class TestCmp { + attr = './script.js'; + } + `, + ); + + env.driveMain(); + + const jsContents = env.getContents('test.js'); + expect(jsContents).toContain( + 'i0.ɵɵattribute("href", ctx.attr, i0.ɵɵsanitizeResourceUrl, "xlink")("href", ctx.attr, i0.ɵɵsanitizeResourceUrl);', + ); + }); + it('should not generate sanitizers for URL properties in hostBindings fn in Component', () => { env.write( `test.ts`,
packages/compiler/src/schema/dom_security_schema.ts+4 −0 modified@@ -119,6 +119,10 @@ export function SECURITY_SCHEMA(): {[k: string]: SecurityContext} { 'object|codebase', 'object|data', 'script|src', + // The below two are for Script SVG + // See: https://developer.mozilla.org/en-US/docs/Web/API/SVGScriptElement/href + 'script|href', + 'script|xlink:href', ]); // Keep this in sync with SECURITY_SENSITIVE_ELEMENTS in packages/core/src/sanitization/sanitization.ts
packages/core/src/sanitization/sanitization.ts+10 −12 modified@@ -213,6 +213,10 @@ export function ɵɵtrustConstantResourceUrl(url: TemplateStringsArray): Trusted return trustedScriptURLFromString(url[0]); } +// Define sets outside the function for O(1) lookups and memory efficiency +const SRC_RESOURCE_TAGS = new Set(['embed', 'frame', 'iframe', 'media', 'script']); +const HREF_RESOURCE_TAGS = new Set(['base', 'link', 'script']); + /** * Detects which sanitizer to use for URL property, based on tag name and prop name. * @@ -221,18 +225,12 @@ export function ɵɵtrustConstantResourceUrl(url: TemplateStringsArray): Trusted * If tag and prop names don't match Resource URL schema, use URL sanitizer. */ export function getUrlSanitizer(tag: string, prop: string) { - if ( - (prop === 'src' && - (tag === 'embed' || - tag === 'frame' || - tag === 'iframe' || - tag === 'media' || - tag === 'script')) || - (prop === 'href' && (tag === 'base' || tag === 'link')) - ) { - return ɵɵsanitizeResourceUrl; - } - return ɵɵsanitizeUrl; + const isResource = + (prop === 'src' && SRC_RESOURCE_TAGS.has(tag)) || + (prop === 'href' && HREF_RESOURCE_TAGS.has(tag)) || + (prop === 'xlink:href' && tag === 'script'); + + return isResource ? ɵɵsanitizeResourceUrl : ɵɵsanitizeUrl; } /**
packages/core/test/bundling/router/bundle.golden_symbols.json+2 −0 modified@@ -115,6 +115,7 @@ "HEADER_OFFSET", "HOST", "HOST_ATTR", + "HREF_RESOURCE_TAGS", "HYDRATION", "HistoryStateManager", "HostAttributeToken", @@ -272,6 +273,7 @@ "SIGNAL", "SIGNAL_NODE", "SIMPLE_CHANGES_STORE", + "SRC_RESOURCE_TAGS", "STABILITY_WARNING_THRESHOLD", "SVG_NAMESPACE", "SafeSubscriber",
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-jrmj-c5cx-3cw6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-22610ghsaADVISORY
- github.com/angular/angular/commit/91dc91bae4a1bbefc58bef6ef739d0e02ab44d56ghsax_refsource_MISCWEB
- github.com/angular/angular/pull/66318ghsax_refsource_MISCWEB
- github.com/angular/angular/security/advisories/GHSA-jrmj-c5cx-3cw6ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.